public class ExtendThreadDemo extends Thread {
public ExtendThreadDemo (String name) {
super(name);
}
// Run method is executed when thread first started
public void run() {
for(int i = 0; i<10; i++) {
System.out.println(i + ": " + getName());
try {
Thread.sleep((long)(Math.random() * 1000));
} catch (InterruptedException ie) {}
}
System.out.println (getName() + " is finished!");
}
// Main method to create and start threads
// main method itself is also a thread which is usually a control thread
public static void main(String args[]) {
// Create first thread instance
Thread t1 = new ExtendThreadDemo("Love me");
// Create second thread instance
Thread t2 = new ExtendThreadDemo("Love me not");
/*
// Make both threads daemon threads
// a daemon thread is a thread that runs for the benefit of other threads
// when only daemons threads remains in the program, the program exists.
t1.setDaemon(true); t2.setDaemon(true);
*/
// Start both threads
// program cannot call run() directly
t1.start(); t2.start();
/*
try {
// Sleep for one second, to allow threads
// time to display first message
Thread.sleep(1000);
} catch (InterruptedException ie) {}
*/
System.out.println("main is DONE");
}
}
public class SleepyHead extends Thread {
// Run method is executed when thread first started
public void run() {
System.out.println ("I feel sleepy. Wake me in eight hours");
try {
// Sleep for eight hours
Thread.sleep( 1000 * 60 * 60 * 8 );
System.out.println ("That was a nice nap");
} catch (InterruptedException ie) {
System.err.println ("Just five more minutes....");
}
}
// Main method to create and start threads
public static void main(String args[]) throws java.io.IOException {
// Create a 'sleepy' thread
Thread sleepy = new SleepyHead();
// Start thread sleeping
sleepy.start();
// Prompt user and wait for input
System.out.println ("Press enter to interrupt the thread");
System.in.read();
// Interrupt the thread
sleepy.interrupt();
}
}
public class StopMe extends Thread {
// Run method is executed when thread first started
public void run() {
int count = 1;
System.out.println ("I can count. Watch me go!");
for (;;) {
// Print count and increment it
System.out.print (count++ + " ");
// Sleep for half a second
try { Thread.sleep(500); } catch (InterruptedException ie) {}
}
}
// Main method to create and start threads
public static void main(String args[]) throws java.io.IOException {
// Create and start counting thread
Thread counter = new StopMe();
counter.start();
// Prompt user and wait for input
System.out.println ("Press any enter to stop the thread counting");
System.in.read();
// Interrupt the thread
counter.stop();
}
}
public class SafeStopMe extends Thread {
// the variable must be volatile (or access to the variable must be
// synchronized)
private static volatile Thread blinker;
// Run method is executed when thread first started
public void run() {
Thread thisThread = Thread.currentThread();
int count = 1;
System.out.println ("I can count. Watch me go!");
while (thisThread == blinker) {
// Print count and increment it
System.out.print (count++ + " ");
// Sleep for half a second
try { Thread.sleep(500); } catch (InterruptedException ie) {}
}
}
// Main method to create and start threads
public static void main(String args[]) throws java.io.IOException {
// Create and start counting thread
blinker = new SafeStopMe();
blinker.start();
// Prompt user and wait for input
System.out.println ("Press any enter to stop the thread counting");
System.in.read();
// Interrupt the thread
blinker = null;
}
}
public class WaitForDeath extends Thread {
// Run method is executed when thread first started
public void run() {
System.out.println ("This thread feels a little ill....");
// Sleep for five seconds
try {
Thread.sleep(5000);
} catch (InterruptedException ie) {}
}
// Main method to create and start threads
public static void main(String args[]) throws java.lang.InterruptedException {
// Create and start dying thread
Thread dying = new WaitForDeath();
dying.start();
// Prompt user and wait for input
System.out.println ("Waiting for thread death");
// Wait till death
dying.join();
System.out.println ("Thread has died");
}
}
public class WaitForDeath extends Thread {
public WaitForDeath (String name) {
super(name);
}
// Run method is executed when thread first started
public void run() {
// Sleep for a while
try {
Thread.sleep((long)(Math.random() * 3000));
} catch (InterruptedException ie) {}
System.out.println(getName() + " has died.");
}
// Main method to create and start threads
public static void main(String args[]) throws java.lang.InterruptedException {
// Create and start dying thread
Thread dying1 = new WaitForDeath("First thread");
dying1.start();
Thread dying2 = new WaitForDeath("Second thread");
dying2.start();
// Prompt user and wait for input
System.out.println ("Waiting for thread death");
// Wait till death
dying1.join(); dying2.join();
System.out.println ("main thread has died");
}
}
// Please run the program and observe the execution order.
// If your CPU speed is faster, you may want to increase the number
// of loops in the following program.
public class PriorityDemo2 extends Thread {
public PriorityDemo2(String name) {
super(name);
}
// Run method is executed when thread first started
public void run() {
int p;
for(int i=0; i<100; i++) {
p = getPriority();
if(p == 5 && i < 10)
System.out.println(i + ": " + getName() + " with priority " +
p + " is done!");
if(p == 6 && i > 90)
System.out.println(i + ": " + getName() + " with priority " +
p + " is done!");
}
}
// Main method to create and start threads
// main method itself is also a thread which is usually a control thread
public static void main(String args[]) {
Thread t1 = new PriorityDemo2("Love me");
Thread t2 = new PriorityDemo2("Love me not");
Thread t3 = new PriorityDemo2("You Guess");
// set priority
t1.setPriority(4); t3.setPriority(6);
// Start both threads
// program cannot call run() directly
t1.start(); t2.start(); t3.start();
System.out.println("main is DONE");
}
}
dns:~/java> java PriorityDemo2 main is DONE 0: Love me not with priority 5 is done! 1: Love me not with priority 5 is done! 2: Love me not with priority 5 is done! 3: Love me not with priority 5 is done! 4: Love me not with priority 5 is done! 5: Love me not with priority 5 is done! 6: Love me not with priority 5 is done! 7: Love me not with priority 5 is done! 8: Love me not with priority 5 is done! 9: Love me not with priority 5 is done! 91: You Guess with priority 6 is done! 92: You Guess with priority 6 is done! 93: You Guess with priority 6 is done! 94: You Guess with priority 6 is done! 95: You Guess with priority 6 is done! 96: You Guess with priority 6 is done! 97: You Guess with priority 6 is done! 98: You Guess with priority 6 is done! 99: You Guess with priority 6 is done!
public class PriorityDemo extends Thread {
public PriorityDemo (String name) {
super(name);
}
// Run method is executed when thread first started
public void run() {
for(int i = 0; i<10; i++) {
int p = getPriority();
System.out.println(i + ": " + getName() + "; " + p);
p = (p + 1) % 10;
if (p == 0) p++;
setPriority(p);
try {
Thread.sleep((long)(Math.random() * 1000));
} catch (InterruptedException ie) {}
}
System.out.println (getName() + " is finished!");
}
public static void main(String args[]) {
Thread t1 = new PriorityDemo("Love me");
Thread t2 = new PriorityDemo("Love me not");
Thread t3 = new PriorityDemo("You Guess");
// set priority
t1.setPriority(Thread.MIN_PRIORITY); t2.setPriority(4);
t3.setPriority(Thread.MAX_PRIORITY);
// Start both threads
// program cannot call run() directly
t1.start(); t2.start(); t3.start();
System.out.println("main is DONE");
}
}
// Fig. 16.4: Buffer.java
// Buffer interface specifies methods called by Producer and Consumer.
public interface Buffer {
public void set( int value ); // place value into Buffer
public int get(); // return value from Buffer
}
// Fig. 16.7: UnsynchronizedBuffer.java
// UnsynchronizedBuffer represents a single shared integer.
public class UnsynchronizedBuffer implements Buffer {
private int buffer = -1; // shared by producer and consumer threads
// place value into buffer
public void set( int value ) {
System.err.println( Thread.currentThread().getName() +
" writes " + value );
buffer = value;
}
// return value from buffer
public int get() {
System.err.println( Thread.currentThread().getName() +
" reads " + buffer );
return buffer;
}
}
// Fig. 16.5: Producer.java
// Producer's run method controls a thread that
// stores values from 1 to 4 in sharedLocation.
public class Producer extends Thread {
private Buffer sharedLocation; // reference to shared object
// constructor
public Producer( Buffer shared ) {
super( "Producer" );
sharedLocation = shared;
}
// store values from 1 to 4 in sharedLocation
public void run() {
for ( int count = 1; count <= 4; count++ ) {
// sleep 0 to 3 seconds, then place value in Buffer
try {
Thread.sleep( ( int ) ( Math.random() * 3001 ) );
sharedLocation.set( count );
}
// if sleeping thread interrupted, print stack trace
catch ( InterruptedException exception ) {
exception.printStackTrace();
}
} // end for
System.err.println( getName() + " done producing." +
"\nTerminating " + getName() + ".");
} // end method run
} // end class Producer
// Fig. 16.6: Consumer.java
// Consumer's run method controls a thread that loops four
// times and reads a value from sharedLocation each time.
public class Consumer extends Thread {
private Buffer sharedLocation; // reference to shared object
// constructor
public Consumer( Buffer shared ) {
super( "Consumer" );
sharedLocation = shared;
}
// read sharedLocation's value four times and sum the values
public void run() {
int sum = 0;
for ( int count = 1; count <= 4; count++ ) {
// sleep 0 to 3 seconds, read value from Buffer and add to sum
try {
Thread.sleep( ( int ) ( Math.random() * 3001 ) );
sum += sharedLocation.get();
}
// if sleeping thread interrupted, print stack trace
catch ( InterruptedException exception ) {
exception.printStackTrace();
}
}
System.err.println( getName() + " read values totaling: " + sum +
".\nTerminating " + getName() + ".");
} // end method run
} // end class Consumer
// Fig. 16.8: SharedBufferTest.java
// SharedBufferTest creates producer and consumer threads.
public class SharedBufferTest {
public static void main( String [] args ) {
// create shared object used by threads
Buffer sharedLocation = new UnsynchronizedBuffer();
// create producer and consumer objects
Producer producer = new Producer( sharedLocation );
Consumer consumer = new Consumer( sharedLocation );
producer.start(); // start producer thread
consumer.start(); // start consumer thread
} // end main
} // end class SharedCell
C:\tmp\examples\ch16\fig16_04_08>java SharedBufferTest Consumer reads -1 Consumer reads -1 Producer writes 1 Producer writes 2 Producer writes 3 Consumer reads 3 Producer writes 4 Producer done producing. Terminating Producer. Consumer reads 4 Consumer read values totaling: 5. Terminating Consumer. C:\tmp\examples\ch16\fig16_04_08>java SharedBufferTest Consumer reads -1 Producer writes 1 Producer writes 2 Consumer reads 2 Consumer reads 2 Consumer reads 2 Consumer read values totaling: 5. Terminating Consumer. Producer writes 3 Producer writes 4 Producer done producing. Terminating Producer.
// Fig. 16.9: SynchronizedBuffer.java
// SynchronizedBuffer synchronizes access to a single shared integer.
public class SynchronizedBuffer implements Buffer {
private int buffer = -1; // shared by producer and consumer threads
private int occupiedBufferCount = 0; // count of occupied buffers
// place value into buffer
public synchronized void set( int value ) {
// for output purposes, get name of thread that called this method
String name = Thread.currentThread().getName();
// while there are no empty locations, place thread in waiting state
while ( occupiedBufferCount == 1 ) {
// output thread information and buffer information, then wait
try {
System.err.println( name + " tries to write." );
displayState( "Buffer full. " + name + " waits." );
wait();
}
// if waiting thread interrupted, print stack trace
catch ( InterruptedException exception ) {
exception.printStackTrace();
}
} // end while
buffer = value; // set new buffer value
// indicate producer cannot store another value
// until consumer retrieves current buffer value
++occupiedBufferCount;
displayState( name + " writes " + buffer );
// Be aware of notify(). It will notify one thread to wake up,
// but cannot ask one specific thread to wake up. So, if you
// not sure how many producer threads are waiting, it is better
// to use notifyAll() to wake all waiting threads up.
notify(); // tell waiting thread to enter ready state
} // end method set; releases lock on SynchronizedBuffer
// return value from buffer
public synchronized int get() {
// for output purposes, get name of thread that called this method
String name = Thread.currentThread().getName();
// while no data to read, place thread in waiting state
while ( occupiedBufferCount == 0 ) {
// output thread information and buffer information, then wait
try {
System.err.println( name + " tries to read." );
displayState( "Buffer empty. " + name + " waits." );
wait();
}
// if waiting thread interrupted, print stack trace
catch ( InterruptedException exception ) {
exception.printStackTrace();
}
} // end while
// indicate that producer can store another value
// because consumer just retrieved buffer value
--occupiedBufferCount;
displayState( name + " reads " + buffer );
notify(); // tell waiting thread to become ready to execute
return buffer;
} // end method get; releases lock on SynchronizedBuffer
// display current operation and buffer state
public void displayState( String operation ) {
StringBuffer outputLine = new StringBuffer( operation );
outputLine.setLength( 40 );
outputLine.append( buffer + "\t\t" + occupiedBufferCount );
System.err.println( outputLine );
System.err.println();
}
} // end class SynchronizedBuffer
// Fig. 16.10: SharedBufferTest2.java
// SharedBufferTest2creates producer and consumer threads.
public class SharedBufferTest2 {
public static void main( String [] args ) {
// create shared object used by threads; we use a SynchronizedBuffer
// reference rather than a Buffer reference so we can invoke
// SynchronizedBuffer method displayState from main
SynchronizedBuffer sharedLocation = new SynchronizedBuffer();
// Display column heads for output
StringBuffer columnHeads = new StringBuffer( "Operation" );
columnHeads.setLength( 40 );
columnHeads.append( "Buffer\t\tOccupied Count" );
System.err.println( columnHeads );
System.err.println();
sharedLocation.displayState( "Initial State" );
// create producer and consumer objects
Producer producer = new Producer( sharedLocation );
Consumer consumer = new Consumer( sharedLocation );
producer.start(); // start producer thread
consumer.start(); // start consumer thread
} // end main
} // end class SharedBufferTest2
public class SynchBlock extends Thread {
static StringBuffer buffer;
static int counter;
public SynchBlock(String s) {
super(s);
buffer = new StringBuffer();
counter= 1;
}
public void run() {
// synchronization lock against a particular object -- buffer
// 其實可以作的更精緻一點,counter 和 buffer 分開 lock
synchronized (buffer) {
int tempVariable = counter++;
// Create message to add to buffer, including linefeed
String message = getName() + ": Count value is : " + tempVariable +
System.getProperty("line.separator");
try {
Thread.sleep(100);
} catch (InterruptedException ie) {}
buffer.append (message);
}
}
public static void main(String args[]) throws Exception {
// Create a new runnable instance
Thread t1 = new SynchBlock("Thread 1");
Thread t2 = new SynchBlock("Thread 2");
Thread t3 = new SynchBlock("Thread 3");
Thread t4 = new SynchBlock("Thread 4");
t1.start(); t2.start(); t3.start(); t4.start();
// Wait for all three threads to finish
t1.join(); t2.join(); t3.join(); t4.join();
System.out.println (buffer);
}
}
public class Deadlock {
static Lock lock1;
static Lock lock2;
static int state;
public static void main(String[] args) {
lock1 = new Lock();
lock2 = new Lock();
Process1 p1 = new Process1();
Process2 p2 = new Process2();
p1.start();
p2.start();
}
}
class Lock {}
class Process1 extends Thread {
public void run() {
Deadlock.state++;
// lock Deaklock.lock1 first and then try to lock Deadlock.lock2
while(true) {
System.out.println("Process 1: " + Deadlock.state);
synchronized (Deadlock.lock1) {
try {
Thread.sleep(( int ) ( Math.random() * 100));
} catch (InterruptedException exception ) {
exception.printStackTrace();
}
synchronized (Deadlock.lock2) {
Deadlock.state++;
}
}
}
}
}
class Process2 extends Thread {
public void run() {
Deadlock.state++;
// lock Deaklock.lock2 first and then try to lock Deadlock.lock1
while(true) {
System.out.println("Process 2: " + Deadlock.state);
synchronized (Deadlock.lock2) {
try {
Thread.sleep(( int ) ( Math.random() * 100));
} catch (InterruptedException exception ) {
exception.printStackTrace();
}
synchronized (Deadlock.lock1) {
Deadlock.state++;
}
}
}
}
}
// java.lang.Thread implements java.lang.Runnable
class RunnableThread implements Runnable {
// Run method is executed when thread first started
public void run() {
System.out.println (Thread.currentThread().getName() +
" is an instance of the Runnable interface");
}
}
public class RunnableThreadDemo {
// Main method to create and start threads
public static void main(String args[]) {
System.out.println ("Creating runnable object");
RunnableThread r = new RunnableThread();
// Create a thread, and pass the runnable object
System.out.println ("Creating first thread");
Thread t1 = new Thread(r, "Thread 1");
// Create a second thread, and pass the runnable object
System.out.println ("Creating second thread");
Thread t2 = new Thread(r, "Thread 2");
// Start both threads
System.out.println ("Starting both threads");
t1.start(); t2.start();
}
}
// Fig. 16.14: CircularBuffer.java
// CircularBuffer synchronizes access to an array of shared buffers.
import javax.swing.*;
public class CircularBuffer implements Buffer {
// each array element is a buffer
private int buffers[] = { -1, -1, -1 };
// occupiedBufferCount maintains count of occupied buffers
private int occupiedBufferCount = 0;
// variables that maintain read and write buffer locations
private int readLocation = 0, writeLocation = 0;
// reference to GUI component that displays output
private JTextArea outputArea;
// constructor
public CircularBuffer( JTextArea output ) {
outputArea = output;
}
// place value into buffer
public synchronized void set( int value ) {
// for output purposes, get name of thread that called this method
String name = Thread.currentThread().getName();
// while there are no empty locations, place thread in waiting state
while ( occupiedBufferCount == buffers.length ) {
// output thread information and buffer information, then wait
try {
SwingUtilities.invokeLater( new RunnableOutput( outputArea,
"\nAll buffers full. " + name + " waits." ) );
wait();
}
// if waiting thread interrupted, print stack trace
catch ( InterruptedException exception )
{
exception.printStackTrace();
}
} // end while
// place value in writeLocation of buffers
buffers[ writeLocation ] = value;
// update Swing GUI component with produced value
SwingUtilities.invokeLater( new RunnableOutput( outputArea,
"\n" + name + " writes " + buffers[ writeLocation ] + " ") );
// just produced a value, so increment number of occupied buffers
++occupiedBufferCount;
// update writeLocation for future write operation
writeLocation = ( writeLocation + 1 ) % buffers.length;
// display contents of shared buffers
SwingUtilities.invokeLater( new RunnableOutput(
outputArea, createStateOutput() ) );
notify(); // return waiting thread (if there is one) to ready state
} // end method set
// return value from buffer
public synchronized int get() {
// for output purposes, get name of thread that called this method
String name = Thread.currentThread().getName();
// while no data to read, place thread in waiting state
while ( occupiedBufferCount == 0 ) {
// output thread information and buffer information, then wait
try {
SwingUtilities.invokeLater( new RunnableOutput( outputArea,
"\nAll buffers empty. " + name + " waits.") );
wait();
}
// if waiting thread interrupted, print stack trace
catch ( InterruptedException exception ) {
exception.printStackTrace();
}
} // end while
// obtain value at current readLocation
int readValue = buffers[ readLocation ];
// update Swing GUI component with consumed value
SwingUtilities.invokeLater( new RunnableOutput( outputArea,
"\n" + name + " reads " + readValue + " ") );
// just consumed a value, so decrement number of occupied buffers
--occupiedBufferCount;
// update readLocation for future read operation
readLocation = ( readLocation + 1 ) % buffers.length;
// display contents of shared buffers
SwingUtilities.invokeLater( new RunnableOutput(
outputArea, createStateOutput() ) );
notify(); // return waiting thread (if there is one) to ready state
return readValue;
} // end method get
// create state output
public String createStateOutput() {
// first line of state information
String output =
"(buffers occupied: " + occupiedBufferCount + ")\nbuffers: ";
for ( int i = 0; i < buffers.length; i++ )
output += " " + buffers[ i ] + " ";
// second line of state information
output += "\n ";
for ( int i = 0; i < buffers.length; i++ )
output += "---- ";
// third line of state information
output += "\n ";
// append readLocation (R) and writeLocation (W)
// indicators below appropriate buffer locations
for ( int i = 0; i < buffers.length; i++ )
if ( i == writeLocation && writeLocation == readLocation )
output += " WR ";
else if ( i == writeLocation )
output += " W ";
else if ( i == readLocation )
output += " R ";
else
output += " ";
output += "\n";
return output;
} // end method createStateOutput
} // end class CircularBuffer
// Fig. 16.11: RunnableOutput.java
// Class RunnableOutput updates JTextArea with output
import javax.swing.*;
public class RunnableOutput implements Runnable {
private JTextArea outputArea;
private String messageToAppend;
// initialize outputArea and message
public RunnableOutput( JTextArea output, String message ) {
outputArea = output;
messageToAppend = message;
}
// method called by SwingUtilities.invokeLater to update outputArea
public void run() {
outputArea.append( messageToAppend );
}
} // end class RunnableOutput
// Fig. 16.12: Producer.java
// Producer?? run method controls a thread that
// stores values from 11 to 20 in sharedLocation.
import javax.swing.*;
public class Producer extends Thread {
private Buffer sharedLocation;
private JTextArea outputArea;
// constructor
public Producer( Buffer shared, JTextArea output ) {
super( "Producer" );
sharedLocation = shared;
outputArea = output;
}
// store values from 11-20 and in sharedLocation's buffer
public void run() {
for ( int count = 11; count <= 20; count ++ ) {
// sleep 0 to 3 seconds, then place value in Buffer
try {
Thread.sleep( ( int ) ( Math.random() * 3000 ) );
sharedLocation.set( count );
}
// if sleeping thread interrupted, print stack trace
catch ( InterruptedException exception ) {
exception.printStackTrace();
}
}
String name = getName();
SwingUtilities.invokeLater( new RunnableOutput( outputArea, "\n" +
name + " done producing.\n" + name + " terminated.\n" ) );
} // end method run
} // end class Producer
// Fig. 16.13: Consumer.java
// Consumer?? run method controls a thread that loops ten
// times and reads a value from sharedLocation each time.
import javax.swing.*;
public class Consumer extends Thread {
private Buffer sharedLocation; // reference to shared object
private JTextArea outputArea;
// constructor
public Consumer( Buffer shared, JTextArea output )
{
super( "Consumer" );
sharedLocation = shared;
outputArea = output;
}
// read sharedLocation's value ten times and sum the values
public void run()
{
int sum = 0;
for ( int count = 1; count <= 10; count++ ) {
// sleep 0 to 3 seconds, read value from Buffer and add to sum
try {
Thread.sleep( ( int ) ( Math.random() * 3001 ) );
sum += sharedLocation.get();
}
// if sleeping thread interrupted, print stack trace
catch ( InterruptedException exception ) {
exception.printStackTrace();
}
}
String name = getName();
SwingUtilities.invokeLater( new RunnableOutput( outputArea,
"\nTotal " + name + " consumed: " + sum + ".\n" +
name + " terminated.\n ") );
} // end method run
} // end class Consumer
// Fig. 16.15: CircularBufferTest.java
// CircularBufferTest shows two threads manipulating a circular buffer.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
// set up the producer and consumer threads and start them
public class CircularBufferTest extends JFrame {
JTextArea outputArea;
// set up GUI
public CircularBufferTest() {
super( "Demonstrating Thread Synchronizaton" );
outputArea = new JTextArea( 20,30 );
outputArea.setFont( new Font( "Monospaced", Font.PLAIN, 12 ) );
getContentPane().add( new JScrollPane( outputArea ) );
setSize( 310, 500 );
setVisible( true );
// create shared object used by threads; we use a CircularBuffer
// reference rather than a Buffer reference so we can invoke
// CircularBuffer method createStateOutput
CircularBuffer sharedLocation = new CircularBuffer( outputArea );
// display initial state of buffers in CircularBuffer
SwingUtilities.invokeLater( new RunnableOutput( outputArea,
sharedLocation.createStateOutput() ) );
// set up threads
Producer producer = new Producer( sharedLocation, outputArea );
Consumer consumer = new Consumer( sharedLocation, outputArea );
producer.start(); // start producer thread
consumer.start(); // start consumer thread
} // end constructor
public static void main ( String args[] ) {
CircularBufferTest application = new CircularBufferTest();
application.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
}
} // end class CirclularBufferTest
// Fig. 16.16: RandomCharacters.java
// Class RandomCharacters demonstrates the Runnable interface
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class RandomCharacters extends JApplet implements ActionListener {
private String alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
private final static int SIZE = 3;
private JLabel outputs[];
private JCheckBox checkboxes[];
private Thread threads[];
private boolean suspended[];
// set up GUI and arrays
public void init() {
outputs = new JLabel[ SIZE ];
checkboxes = new JCheckBox[ SIZE ];
threads = new Thread[ SIZE ];
suspended = new boolean[ SIZE ];
Container container = getContentPane();
container.setLayout( new GridLayout( SIZE, 2, 5, 5 ) );
// create GUI components, register listeners and attach
// components to content pane
for ( int count = 0; count < SIZE; count++ ) {
outputs[ count ] = new JLabel();
outputs[ count ].setBackground( Color.GREEN );
outputs[ count ].setOpaque( true );
container.add( outputs[ count ] );
checkboxes[ count ] = new JCheckBox( "Suspended" );
checkboxes[ count ].addActionListener( this );
container.add( checkboxes[ count ] );
}
} // end method init
// create and start threads each time start is called (i.e., after
// init and when user revists Web page containing this applet)
public void start() {
for ( int count = 0; count < threads.length; count++ ) {
// create Thread; initialize object that implements Runnable
threads[ count ] =
new Thread( new RunnableObject(), "Thread " + ( count + 1 ) );
threads[ count ].start(); // begin executing Thread
}
}
// determine thread location in threads array
private int getIndex( Thread current ) {
for ( int count = 0; count < threads.length; count++ )
if ( current == threads[ count ] )
return count;
return -1;
}
// called when user switches Web pages; stops all threads
public synchronized void stop() {
// set references to null to terminate each thread's run method
for ( int count = 0; count < threads.length; count++ )
threads[ count ] = null;
notifyAll(); // notify all waiting threads, so they can terminate
}
// handle button events
public synchronized void actionPerformed( ActionEvent event ) {
for ( int count = 0; count < checkboxes.length; count++ ) {
if ( event.getSource() == checkboxes[ count ] ) {
suspended[ count ] = !suspended[ count ];
// change label color on suspend/resume
outputs[ count ].setBackground(
suspended[ count ] ? Color.RED : Color.GREEN );
// if thread resumed, make sure it starts executing
if ( !suspended[ count ] )
notifyAll();
return;
}
}
} // end method actionPerformed
// private inner class that implements Runnable to control threads
private class RunnableObject implements Runnable {
// place random characters in GUI, variables currentThread and
// index are final so can be used in an anonymous inner class
public void run() {
// get reference to executing thread
final Thread currentThread = Thread.currentThread();
// determine thread's position in array
final int index = getIndex( currentThread );
// loop condition determines when thread should stop; loop
// terminates when reference threads[ index ] becomes null
while ( threads[ index ] == currentThread ) {
// sleep from 0 to 1 second
try {
Thread.sleep( ( int ) ( Math.random() * 1000 ) );
// determine whether thread should suspend execution;
// synchronize on RandomCharacters applet object
synchronized( RandomCharacters.this ) {
while ( suspended[ index ] &&
threads[ index ] == currentThread ) {
// temporarily suspend thread execution
RandomCharacters.this.wait();
}
} // end synchronized block
} // end try
// if thread interrupted during wait/sleep, print stack trace
catch ( InterruptedException exception ) {
exception.printStackTrace();
}
// display character on corresponding JLabel
SwingUtilities.invokeLater(
new Runnable() {
// pick random character and display it
public void run() {
char displayChar =
alphabet.charAt( ( int ) ( Math.random() * 26 ) );
outputs[ index ].setText(
currentThread.getName() + ": " + displayChar );
}
} // end inner class
); // end call to SwingUtilities.invokeLater
} // end while
System.err.println( currentThread.getName() + " terminating" );
} // end method run
} // end private inner class RunnableObject
} // end class RandomCharacters
import java.io.*;
public class PipeDemo extends Thread {
PipedOutputStream output;
// Create an instance of the PipeDemo class
public PipeDemo(PipedOutputStream out) {
// Copy to local member variable
output = out;
}
public static void main (String args[]) {
try {
// Create a pipe for writing
PipedOutputStream pout = new PipedOutputStream();
// Create a new pipe demo thread, to write to our pipe
PipeDemo pipedemo = new PipeDemo(pout);
// One communication pipe is attached to a inputstream and a
// an outputstream at both ends; respectively.
//
// Creates a piped input stream connected to the specified piped
// output stream. Data bytes written to pout will then be available
// as input from pin.
PipedInputStream pin = new PipedInputStream(pout);
// Start the thread
pipedemo.start();
// Read thread data,
int input = pin.read();
// Terminate when end of stream reached
while (input != -1) {
// Print message
System.out.print ( (char) input);
// Read next byte
input = pin.read();
}
} catch (Exception e) {
System.err.println ("Pipe error " + e);
}
}
public void run() {
try {
// Create a printstream for convenient writing
PrintStream p = new PrintStream( output );
// Print message
p.println ("Hello from another thread, via pipes!");
// Close the stream
p.close();
} catch (Exception e) {
// no code req'd
}
}
}
import java.io.*;
class PipeThread extends Thread {
PipedOutputStream output;
PipedInputStream input;
public PipeThread(String s, PipedOutputStream out, PipedInputStream in) {
super(s);
output = out;
input = in;
}
public void run() {
PrintStream p;
BufferedReader r;
try {
p = new PrintStream(output);
r = new BufferedReader(new InputStreamReader(input));
// Print message
p.println ("你好 from " + getName());
System.out.println(getName() + " received: " + r.readLine());
} catch (Exception e) {
// no code req'd
}
}
}
public class PipeDemo2 {
public static void main (String args[]) {
try {
// create two communication pipes
// NOTE that the pipe (including both PipedOutputStream
// and PipedInputStream) must be constructed before the thread is started
PipedOutputStream pout1 = new PipedOutputStream();
PipedInputStream pin1 = new PipedInputStream(pout1);
PipedOutputStream pout2 = new PipedOutputStream();
PipedInputStream pin2 = new PipedInputStream(pout2);
// Create a new pipe demo thread, to write to our pipe
PipeThread pipedemo1 = new PipeThread("Thread 1", pout1, pin2);
PipeThread pipedemo2 = new PipeThread("Thread 2", pout2, pin1);
// Start the thread
pipedemo1.start(); pipedemo2.start();
} catch (Exception e) {}
}
}
// Chapter 7, Listing 10
public class GroupDemo implements Runnable {
public static void main(String args[]) throws Exception {
// Create a thread group
ThreadGroup parent = new ThreadGroup("parent");
// Create a group that is a child of another thread group
ThreadGroup subgroup = new ThreadGroup(parent, "subgroup");
// Create some threads in the parent, and subgroup class
Thread t1 = new Thread ( parent, new GroupDemo() );
t1.start();
Thread t2 = new Thread ( parent, new GroupDemo() );
t2.start();
Thread t3 = new Thread ( subgroup, new GroupDemo() );
t3.start();
// Dump the contents of the group to System.out
parent.list();
// Wait for user, then terminate
System.out.println ("Press enter to continue");
System.in.read();
System.exit(0);
}
public void run() {
// Do nothing
for(;;) {
Thread.yield();
}
}
}