Sponsored Link •
|
Thread
java.lang.Thread
Thread
or implementing Runnable
1 // In file threads/ex1/RepetitiveThread.java 2 public class RepetitiveThread extends Thread { 3 4 private final String msg; 5 private final long sleepTime; 6 7 public RepetitiveThread(String msg, long sleepTime) { 8 this.msg = msg; 9 this.sleepTime = sleepTime; 10 } 11 12 public void run() { 13 14 for (;;) { 15 16 System.out.println(msg); 17 try { 18 sleep(sleepTime); 19 } 20 catch (InterruptedException e) { 21 } 22 } 23 } 24 } 1 // In file threads/ex1/Example1.java 2 public class Example1 { 3 4 // Args to this application specify "msg" 5 // and "sleepTime" for multiple threads. 6 // For example, the command: 7 // 8 // $ java Example1 Hi 100 Lo 1000 9 // 10 // requests two threads, one that prints 11 // out "Hi" every 100 milliseconds and 12 // another that prints out "Lo" every 13 // 1000 milliseconds. 14 // 15 public static void main(String[] args) { 16 17 // Require an even argCount 18 int argCount = args.length; 19 if ((argCount / 2) == 1) { 20 --argCount; 21 } 22 23 for (int i = 0; i < argCount; i += 2) { 24 25 String msg = args[i]; 26 long sleepTime = Long.parseLong(args[i + 1]); 27 28 RepetitiveThread rt = 29 new RepetitiveThread(msg, sleepTime); 30 31 rt.start(); 32 } 33 } 34 }
Thread
often difficult because its hard to
fit Thread
into the inheritance hierarchy.
Runnable
Runnable
than extend
Thread
:
1 // In file threads/ex2/Animal.java 2 public class Animal { 3 } 1 // In file threads/ex2/Cat.java 2 public class Cat extends Animal implements Runnable { 3 4 private final String msg; 5 private final long sleepTime; 6 7 public Cat(String msg, long sleepTime) { 8 this.msg = msg; 9 this.sleepTime = sleepTime; 10 } 11 12 public void run() { 13 14 for (;;) { 15 16 System.out.println(msg); 17 try { 18 Thread.sleep(sleepTime); 19 } 20 catch (InterruptedException e) { 21 } 22 } 23 } 24 } 1 // In Source Packet in file threads/ex2/Example2.java 2 public class Example2 { 3 4 // Args to this application specify "msg" 5 // and "sleepTime" for multiple threads. 6 // For example, the command: 7 // 8 // $ java Example1 Meow 100 Grrr 1000 9 // 10 // requests two threads, one that prints 11 // out "Meow" every 100 milliseconds and 12 // another that prints out "Grrr" every 13 // 1000 milliseconds. 14 // 15 public static void main(String[] args) { 16 17 // Require an even argCount 18 int argCount = args.length; 19 if ((argCount / 2) == 1) { 20 --argCount; 21 } 22 23 for (int i = 0; i < argCount; i += 2) { 24 25 String msg = args[i]; 26 long sleepTime = Long.parseLong(args[i + 1]); 27 28 Cat cat = new Cat(msg, sleepTime); 29 30 Thread catThread = new Thread(cat); 31 catThread.start(); 32 } 33 } 34 }
RGBColor
object (not thread-safe)
1 // In file objectidioms/ex6/RGBColor.java 2 // Instances of this class are NOT thread-safe. 3 4 public class RGBColor { 5 6 private int r; 7 private int g; 8 private int b; 9 10 public RGBColor(int r, int g, int b) { 11 12 checkRGBVals(r, g, b); 13 14 this.r = r; 15 this.g = g; 16 this.b = b; 17 } 18 19 public void setColor(int r, int g, int b) { 20 21 checkRGBVals(r, g, b); 22 23 this.r = r; 24 this.g = g; 25 this.b = b; 26 } 27 28 /** 29 * returns color in an array of three ints: R, G, and B 30 */ 31 public int[] getColor() { 32 33 int[] retVal = new int[3]; 34 retVal[0] = r; 35 retVal[1] = g; 36 retVal[2] = b; 37 38 return retVal; 39 } 40 41 public void invert() { 42 43 r = 255 - r; 44 g = 255 - g; 45 b = 255 - b; 46 } 47 48 private static void checkRGBVals(int r, int g, int b) { 49 50 if (r < 0 || r > 255 || g < 0 || g > 255 || 51 b < 0 || b > 255) { 52 53 throw new IllegalArgumentException(); 54 } 55 } 56 }
Thread | Statement | r | g | b | Color |
none | object represents green | 0 | 255 | 0 | GREEN |
blue | blue thread invokes setColor(0, 0, 255) | 0 | 255 | 0 | GREEN |
blue | checkRGBVals(0, 0, 255); |
0 | 255 | 0 | GREEN |
blue | this.r = 0; |
0 | 255 | 0 | GREEN |
blue | this.g = 0; |
0 | 255 | 0 | GREEN |
blue | blue gets preempted | 0 | 0 | 0 | BLACK |
red | red thread invokes setColor(255, 0, 0) | 0 | 0 | 0 | BLACK |
red | checkRGBVals(255, 0, 0); |
0 | 0 | 0 | BLACK |
red | this.r = 255; |
0 | 0 | 0 | BLACK |
red | this.g = 0; |
255 | 0 | 0 | RED |
red | this.b = 0; |
255 | 0 | 0 | RED |
red | red thread returns | 255 | 0 | 0 | RED |
blue | later, blue thread continues | 255 | 0 | 0 | RED |
blue | this.b = 255 |
255 | 0 | 0 | RED |
blue | blue thread returns | 255 | 0 | 255 | MAGENTA |
none | object represents magenta | 255 | 0 | 255 | MAGENTA |
Thread | Statement | r | g | b | Color |
none | object represents green | 0 | 255 | 0 | GREEN |
blue | blue thread invokes setColor(0, 0, 255) | 0 | 255 | 0 | GREEN |
blue | checkRGBVals(0, 0, 255); |
0 | 255 | 0 | GREEN |
blue | this.r = 0; |
0 | 255 | 0 | GREEN |
blue | this.g = 0; |
0 | 255 | 0 | GREEN |
blue | blue gets preempted | 0 | 0 | 0 | BLACK |
red | red thread invokes getColor() | 0 | 0 | 0 | BLACK |
red | int[] retVal = new int[3]; |
0 | 0 | 0 | BLACK |
red | retVal[0] = 0; |
0 | 0 | 0 | BLACK |
red | retVal[1] = 0; |
0 | 0 | 0 | BLACK |
red | retVal[2] = 0; |
0 | 0 | 0 | BLACK |
red | return retVal; |
0 | 0 | 0 | BLACK |
red | red thread returns black | 0 | 0 | 0 | BLACK |
blue | later, blue thread continues | 0 | 0 | 0 | BLACK |
blue | this.b = 255 |
0 | 0 | 0 | BLACK |
blue | blue thread returns | 0 | 0 | 255 | BLUE |
none | object represents blue | 0 | 0 | 255 | BLUE |
RGBColor
Object1 // In file objectidioms/ex7/RGBColor.java 2 // Instances of this class are thread-safe. 3 4 public class RGBColor { 5 6 private int r; 7 private int g; 8 private int b; 9 10 public RGBColor(int r, int g, int b) { 11 12 checkRGBVals(r, g, b); 13 14 this.r = r; 15 this.g = g; 16 this.b = b; 17 } 18 19 public void setColor(int r, int g, int b) { 20 21 checkRGBVals(r, g, b); 22 23 synchronized (this) { 24 25 this.r = r; 26 this.g = g; 27 this.b = b; 28 } 29 } 30 31 /** 32 * returns color in an array of three ints: R, G, and B 33 */ 34 public int[] getColor() { 35 36 int[] retVal = new int[3]; 37 38 synchronized (this) { 39 40 retVal[0] = r; 41 retVal[1] = g; 42 retVal[2] = b; 43 } 44 45 return retVal; 46 } 47 48 public synchronized void invert() { 49 50 r = 255 - r; 51 g = 255 - g; 52 b = 255 - b; 53 } 54 55 private static void checkRGBVals(int r, int g, int b) { 56 57 if (r < 0 || r > 255 || g < 0 || g > 255 || 58 b < 0 || b > 255) { 59 60 throw new IllegalArgumentException(); 61 } 62 } 63 }
Thread | Statement | r | g | b | Color |
none | object represents green | 0 | 255 | 0 | GREEN |
blue | blue thread invokes setColor(0, 0, 255) | 0 | 255 | 0 | GREEN |
blue | checkRGBVals(0, 0, 255); |
0 | 255 | 0 | GREEN |
blue | blue thread acquires lock | 0 | 255 | 0 | GREEN |
blue | this.r = 0; |
0 | 255 | 0 | GREEN |
blue | this.g = 0; |
0 | 255 | 0 | GREEN |
blue | blue gets preempted | 0 | 0 | 0 | BLACK |
red | red thread invokes setColor(255, 0, 0) | 0 | 0 | 0 | BLACK |
red | checkRGBVals(255, 0, 0); |
0 | 0 | 0 | BLACK |
red | red thread blocks because object locked | 0 | 0 | 0 | BLACK |
blue | later, blue thread continues | 0 | 0 | 0 | BLACK |
blue | this.b = 255 |
0 | 0 | 0 | BLACK |
blue | blue thread returns and releases lock | 0 | 0 | 255 | BLUE |
red | later, red thread acquires lock and continues | 0 | 0 | 255 | BLUE |
red | this.r = 255; |
0 | 0 | 255 | BLUE |
red | this.g = 0; |
255 | 0 | 255 | MAGENTA |
red | this.b = 0; |
255 | 0 | 255 | MAGENTA |
red | red thread returns and releases lock | 255 | 0 | 0 | RED |
none | object represents red | 255 | 0 | 0 | RED |
// In file Cat.java public class Cat { public static final int MAX_LIVES = 9; private static Cat[] lives = new Cat[MAX_LIVES]; public static synchronized Cat[] getLives() { return lives; } //... }
java.lang.Class
object.
Thread | Action | Data |
consumer | Any Data? | none |
consumer | WAIT | none |
producer | Buffer Full? | none |
producer | Give | 1, 2, 3 |
producer | NOTIFY | 1, 2, 3 |
producer | Process | 1, 2, 3 |
consumer | Any Data? | 1, 2, 3 |
consumer | Take | none |
consumer | NOTIFY | none |
consumer | Process | none |
consumer | Any Data? | none |
consumer | WAIT | none |
producer | Buffer Full? | none |
producer | Give | 5, 7, 11 |
producer | NOTIFY | 5, 7, 11 |
producer | Process | 5, 7, 11 |
producer | Buffer Full? | 5, 7, 11 |
producer | WAIT | 5, 7, 11 |
consumer | Any Data? | 5, 7, 11 |
consumer | Take | none |
consumer | NOTIFY | none |
consumer | Process | none |
producer | Buffer Full? | none |
producer | Give | 13, 17, 19 |
producer | NOTIFY | 13, 17, 19 |
producer | Process | 13, 17, 19 |
consumer | Any Data? | 13, 17, 19 |
consumer | Take | none |
consumer | NOTIFY | none |
consumer | Process | none |
consumer | Any Data? | none |
consumer | WAIT | none |
1 // In file threads/ex6/IntBuffer.java 2 public class IntBuffer { 3 4 private final int buffSize; 5 private int[] buff; 6 7 // Keeps track of next buff array location 8 // to be filled. When nextBuffIndex == 9 // buffSize, the buffer is full. When 10 // nextBuffIndex == 0, the buffer is 11 // empty. 12 private int nextBuffIndex; 13 14 IntBuffer(int buffSize) { 15 16 this.buffSize = buffSize; 17 buff = new int[buffSize]; 18 } 19 20 public synchronized void add(int val) { 21 22 while (nextBuffIndex == buffSize) { 23 24 try { 25 wait(); 26 } 27 catch (InterruptedException e) { 28 } 29 } 30 31 buff[nextBuffIndex] = val; 32 ++nextBuffIndex; 33 34 notifyAll(); 35 } 36 37 public synchronized int removeNext() { 38 39 while (nextBuffIndex == 0) { 40 41 try { 42 wait(); 43 } 44 catch (InterruptedException e) { 45 } 46 } 47 48 // This buffer is FIFO, so remove the 49 // first int added and shift the rest 50 // over. 51 int val = buff[0]; 52 53 --nextBuffIndex; 54 for (int i = 0; i < nextBuffIndex; ++i) { 55 56 buff[i] = buff[i + 1]; 57 } 58 59 notifyAll(); 60 return val; 61 } 62 } 1 // In file threads/ex6/PrimeNumberGenerator.java 2 public class PrimeNumberGenerator implements Runnable { 3 4 private final IntBuffer buff; 5 6 public PrimeNumberGenerator(IntBuffer buff) { 7 8 this.buff = buff; 9 } 10 11 public void run() { 12 13 int primeNum = 1; 14 int numToCheck = 2; 15 16 buff.add(primeNum); 17 18 for (;;) { 19 20 boolean foundPrime = true; 21 22 for (int divisor = numToCheck / 2; divisor > 1; 23 --divisor) { 24 25 if (numToCheck % divisor == 0) { 26 foundPrime = false; 27 break; 28 } 29 } 30 31 if (foundPrime) { 32 primeNum = numToCheck; 33 buff.add(primeNum); 34 } 35 36 ++numToCheck; 37 } 38 } 39 } 1 // In source packet in file threads/ex6/IntPrinter.java 2 public class IntPrinter implements Runnable { 3 4 private final IntBuffer buff; 5 6 public IntPrinter(IntBuffer buff) { 7 8 this.buff = buff; 9 } 10 11 public void run() { 12 13 for (;;) { 14 15 int val = buff.removeNext(); 16 System.out.println(val); 17 } 18 } 19 } 1 // In file threads/ex6/Example6.java 2 public class Example6 { 3 4 public static void main(String[] args) { 5 6 IntBuffer buff = new IntBuffer(3); 7 8 PrimeNumberGenerator png = new PrimeNumberGenerator(buff); 9 IntPrinter ip = new IntPrinter(buff); 10 11 Thread producer = new Thread(png); 12 Thread consumer = new Thread(ip); 13 14 producer.start(); 15 consumer.start(); 16 } 17 }
sleep()
)
wait()
)
setPriority()
.
yield()
indicates to the JVM that you are ready
for a rest.
Create a Java application named Problem1
that generates the Fibonacci
sequence. The first two numbers of the Fibonacci sequence are 1 and 1. Each
subsequent number is calculated by summing the previous two numbers, as in:
1, 1, 2, 3, 5, 8, 13, 21, 34, 55, and so on.
The Problem1
application will write the
Fibonacci sequence to the standard output.
The Problem1
application, which requires no command line
arguments, should print out the first 92 Fibonacci numbers
The output will look like:
1 1 2 3 5 8 13 <...>The maximum of 92 arises because the 93rd Fibonacci number is too big to express in a Java long. The biggest Fibonacci number that will fit in Java's
long
(a 64 bit signed integer) is 7540113804746346429L, which is
the 92nd Fibonacci number.
The application will be made up of four classes, named:
FibonacciGenerator.java LongBuffer.java LongBufferToOutputThread.java Problem1.java
The application will contain three threads, the main thread and two
extra threads that the main thread will start. The two extra threads are
defined by FibonacciGenerator
, which
implements Runnable
, and LongBufferToOutputThread
,
which directly subclasses class Thread
.
The main()
method of the Problem1
application will create
and start these two threads and connect the output of the
FibonacciGenerator
thread to the input of the
LongBufferToOutputThread
. The Fibonacci
numbers will be generated by the FibonacciGenerator
thread, which writes one
long
value at time into a LongBuffer
.
The LongBufferToOutputThread
will then read long
's
from the LongBuffer
and write them to the standard output.
The main()
method should:
LongBuffer
object with a buffer size of 3.
FibonacciGenerator
. object
LongBufferToOutputThread
object.
FibonacciGenerator
and
LongBufferToOutputThread
threads.
main()
method.
You can base this class on the IntBuffer
class from the
lecture slides, which is in the Threads/examples/ex6
directory of the sample code:
// In source packet in file threads/ex6/IntBuffer.java public class IntBuffer { private final int buffSize; private int[] buff; // Keeps track of next buff array location // to be filled. When nextBuffIndex == // buffSize, the buffer is full. When // nextBuffIndex == 0, the buffer is // empty. private int nextBuffIndex; IntBuffer(int buffSize) { this.buffSize = buffSize; buff = new int[buffSize]; } public synchronized void add(int val) { while (nextBuffIndex == buffSize) { try { wait(); } catch (InterruptedException e) { } } buff[nextBuffIndex] = val; ++nextBuffIndex; notifyAll(); } public synchronized int removeNext() { while (nextBuffIndex == 0) { try { wait(); } catch (InterruptedException e) { } } // This buffer is FIFO, so remove the // first int added and shift the rest // over. int val = buff[0]; --nextBuffIndex; for (int i = 0; i < nextBuffIndex; ++i) { buff[i] = buff[i + 1]; } notifyAll(); return val; } }
Basically, LongBuffer
has to do a similar thing to what
IntBuffer
does, but for long
s instead of
int
s. It needs an add()
method and a long
removeNext()
method, and it must assume different threads will be calling these methods.
Thus, the add()
and removeNext()
methods must be
synchronized and use wait()
and notifyAll()
.
FibonacciGenerator
This class extends Object
and implements Runnable
. It has
one constructor, which takes one argument: a LongBuffer
reference.
It's run()
method simply produces the Fibonacci sequence one
long
at a time and writes each one to the LongBuffer
as it is
produced.
To indicate that it is finished producing numbers, the FibonacciGenerator
class declares a public static final int END_OF_DATA
field that is initialized to
-1
. When the FibonacciGenerator
's
run()
method is done generating the first 92
Fibonacci numbers, it writes an
END_OF_DATA
to the LongBuffer
. After that, this thread is
finished and the run()
method simply returns.
LongBufferToOutputThread
This class extends Thread
. It has one constructor, which takes
one argument: a LongBuffer
.
It's run()
method simply reads one long
at a time
from the LongBuffer
and writes it as a String
to the
standard output, placing a return ('\n'
) after each number
it prints.
It keeps doing this until it reads an
FibonacciGenerator.END_OF_DATA
from the
LongBuffer
. When it finds END_OF_DATA
, the
run()
method returns, and this thread
expires.
How the app knows to terminate: A Java application terminates when all non-daemon threads expire.
In this application, there are three non-daemon threads. The main thread sets up and starts the other two
threads, then returns. One thread down. The FibonacciGenerator
thread
generates the numbers, stores them into the LongBuffer
, then writes an
END_OF_DATA
into the LongBuffer
, and returns. By returning
from run()
, the FibonacciGenerator
thread expires. Two
threads down. The LongBufferToOutputThread
reads from the
LongBuffer
and writes to the standard output until it finds an
END_OF_DATA
in the LongBuffer
. It then
returns. By returning from run()
, the
LongBufferToOutputThread
thread expires.
Because this is the third and only remaining
non-daemon thread, the entire application terminates.
Sponsored Links
|