//: c14:Blocking.java // From Thinking in Java, 2nd Edition // Available at http://www.BruceEckel.com // (c) Bruce Eckel 1999 // Copyright notice in Copyright.txt // Demonstrates the various ways a thread // can be blocked. // // import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.io.*; //////////// The basic framework /////////// class Blockable extends Thread { private Peeker peeker; protected JTextField state = new JTextField(30); protected int i; public Blockable(Container c) { c.add(state); peeker = new Peeker(this, c); } public synchronized int read() { return i; } protected synchronized void update() { state.setText(getClass().getName() + " state: i = " + i); } public void stopPeeker() { // peeker.stop(); Deprecated in Java 1.2 peeker.terminate(); // The preferred approach } } class Peeker extends Thread { private Blockable b; private int session; private JTextField status = new JTextField(30); private boolean stop = false; public Peeker(Blockable b, Container c) { c.add(status); this.b = b; start(); } public void terminate() { stop = true; } public void run() { while (!stop) { status.setText(b.getClass().getName() + " Peeker " + (++session) + "; value = " + b.read()); try { sleep(100); } catch (InterruptedException e){} } } } ///:Continued ///:Continuing ///////////// Blocking via sleep() /////////// class Sleeper1 extends Blockable { public Sleeper1(Container c) { super(c); } public synchronized void run() { while(true) { i++; update(); try { sleep(1000); } catch (InterruptedException e){} } } } class Sleeper2 extends Blockable { public Sleeper2(Container c) { super(c); } public void run() { while(true) { change(); try { sleep(1000); } catch (InterruptedException e){} } } public synchronized void change() { i++; update(); } } ///:Continued ///:Continuing /////////// Blocking via suspend() /////////// class SuspendResume extends Blockable { public SuspendResume(Container c) { super(c); new Resumer(this); } } class SuspendResume1 extends SuspendResume { public SuspendResume1(Container c) { super(c);} public synchronized void run() { while(true) { i++; update(); suspend(); // Deprecated in Java 1.2 } } } class SuspendResume2 extends SuspendResume { public SuspendResume2(Container c) { super(c);} public void run() { while(true) { change(); suspend(); // Deprecated in Java 1.2 } } public synchronized void change() { i++; update(); } } class Resumer extends Thread { private SuspendResume sr; public Resumer(SuspendResume sr) { this.sr = sr; start(); } public void run() { while(true) { try { sleep(1000); } catch (InterruptedException e){} sr.resume(); // Deprecated in Java 1.2 } } } ///:Continued ///:Continuing /////////// Blocking via wait() /////////// class WaitNotify1 extends Blockable { public WaitNotify1(Container c) { super(c); } public synchronized void run() { while(true) { i++; update(); try { wait(1000); } catch (InterruptedException e){} } } } class WaitNotify2 extends Blockable { public WaitNotify2(Container c) { super(c); new Notifier(this); } public synchronized void run() { while(true) { i++; update(); try { wait(); } catch (InterruptedException e){} } } } class Notifier extends Thread { private WaitNotify2 wn2; public Notifier(WaitNotify2 wn2) { this.wn2 = wn2; start(); } public void run() { while(true) { try { sleep(2000); } catch (InterruptedException e){} synchronized(wn2) { wn2.notify(); } } } } ///:Continued ///:Continuing class Sender extends Blockable { // send private Writer out; public Sender(Container c, Writer out) { super(c); this.out = out; } public void run() { while(true) { for(char c = 'A'; c <= 'z'; c++) { try { i++; out.write(c); state.setText("Sender sent: " + (char)c); sleep((int)(3000 * Math.random())); } catch (InterruptedException e){} catch (IOException e) {} } } } } class Receiver extends Blockable { private Reader in; public Receiver(Container c, Reader in) { super(c); this.in = in; } public void run() { try { while(true) { i++; // Show peeker it's alive // Blocks until characters are there: state.setText("Receiver read: " + (char)in.read()); } } catch(IOException e) { e.printStackTrace();} } } ///:Continued ///:Continuing /////////// Testing Everything /////////// public class Blocking extends JApplet { private JButton start = new JButton("Start"), stopPeekers = new JButton("Stop Peekers"); private boolean started = false; private Blockable[] b; private PipedWriter out; private PipedReader in; public void init() { Container cp = getContentPane(); cp.setLayout(new FlowLayout()); out = new PipedWriter(); try { in = new PipedReader(out); } catch(IOException e) {} b = new Blockable[] { new Sleeper1(cp), new Sleeper2(cp), new SuspendResume1(cp), new SuspendResume2(cp), new WaitNotify1(cp), new WaitNotify2(cp), new Sender(cp, out), new Receiver(cp, in) }; start.addActionListener(new StartL()); cp.add(start); stopPeekers.addActionListener( new StopPeekersL()); cp.add(stopPeekers); } class StartL implements ActionListener { public void actionPerformed(ActionEvent e) { if(!started) { started = true; for(int i = 0; i < b.length; i++) b[i].start(); } } } class StopPeekersL implements ActionListener { public void actionPerformed(ActionEvent e) { // Demonstration of the preferred // alternative to Thread.stop(): for(int i = 0; i < b.length; i++) b[i].stopPeeker(); } } public static void main(String[] args) { JApplet applet = new Blocking(); JFrame frame = new JFrame("Blocking"); frame.addWindowListener( new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } }); frame.getContentPane().add(applet); frame.setSize(350,550); applet.init(); applet.start(); frame.setVisible(true); } } ///:~