Threads Theory can we run parts of an application at the same time o multiple lines in a single program can be run simultaneously o as long as they do not depend on each other o BUT they could both be accessing the same data repository have to be careful here two ways of doing this o create two applications that run threads at the same time o create one application that runs two or more threads at the same time how the CPU copes with threads and multiple threads o a regular thread takes resources from the computer/CPU registers stack memory o multiple threads will break up these resources further threads will also have priorities o the higher the priority the more it should run but should also finish faster so the others can run talk more about this later monitors 1
43
Embed
faculty.cse.tamu.edufaculty.cse.tamu.edu/slupoli/notes/Java/old/ThreadsNotes.docx · Web viewThreads. Theory. can we run parts of an application at the same time. multiple lines
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
ThreadsTheory
can we run parts of an application at the same timeo multiple lines in a single program can be run simultaneouslyo as long as they do not depend on each othero BUT they could both be accessing the same data repository
have to be careful here two ways of doing this
o create two applications that run threads at the same timeo create one application that runs two or more threads at the same time
how the CPU copes with threads and multiple threadso a regular thread takes resources from the computer/CPU
registers stack memory
o multiple threads will break up these resources further threads will also have priorities
o the higher the priority the more it should run but should also finish faster so the others can run talk more about this later
monitorso synchronization
synchronous operation blocks a process till the thread completes we can synchronize data members and functions that threads may
shareo asynchronous
is non-blocking and only initiates the thread all data members that threads may share are open to access at any
time by default, this is the setting
1
The Thread Class Basics start
o creates the thread, and allocates resourceso but does not start yet!
runo starts the threado start should be called first
isInterrupted as of Java 6
o http://docs.oracle.com/javase/6/docs/api/java/lang/Thread.html o look at
get/setPriority() isAlive()/isInterrupted join()
allows one thread to wait for the completion of another weird name for the function can put multiple threads in a block to order them in some
fashion sleep()
duh The thread does not lose ownership of any monitors
stop() yield()
Learning from Basic Examples and Setup Counter01.java
o runs a Thread within the GUI application uses sleep starts when we get to the line in the program
no glorified “start” runs within a for loop that displays values from 10 to 0
Demonstrates how to open a window with Swing and count down from 10 in big giant letters.*/
import javax.swing.*;import java.awt.Font ;
public class Counter01 {
public static void main( String[] args ) {
try {
// Create a window with Swing // JFrame frame = new JFrame( "HelloJava" ); JLabel label = new JLabel("Hello, Java!", JLabel.CENTER ); label.setFont( new Font("Serif", Font.BOLD, 36) ) ; frame.getContentPane().add( label ); frame.setSize( 300, 300 ); frame.setVisible( true );
// wait a 5 seconds .. Thread.sleep(5000) ;
for(int i = 10 ; i >= 0 ; i--) {
// change the label in the window label.setText( Integer.toString(i) ) ; Thread.sleep(500) ;
}
label.setText("Kaboom!") ; Thread.sleep(5000);
} catch ( InterruptedException e ) {
// we might get interrupted while we sleep System.out.println("Oh look! an exception!") ;
}
// Calling exit is necessary because the Swing window manager // will keep running System.exit(0) ; }
}
3
Counter02o overall the same, but set is differento use an inner class called Window to do the worko the function “doThis” is introduced
do this calls the inner class Window to get the whole application started
o use the function run() to start everything thread related run is called from the OUTTER class
o see in action
Counter02.java/* File: Counter02.java
Same as Counter01, except now we put the code for counting down in a private inner class, with a method called run.
*/
import javax.swing.*;import java.awt.Font;
public class Counter02 {
// a private inner class private class Window1 {
int start;
// start counting down from 10 by default Window1() { start = 10; }
// this constructor lets me specify the starting point Window1(int n) { start = n; }
void run() {
try {
// Create a window with Swing // JFrame frame = new JFrame( "HelloJava" ); JLabel label = new JLabel("Hello, Java!", JLabel.CENTER ); label.setFont( new Font("Serif", Font.BOLD, 36) ); frame.getContentPane().add( label ); frame.setSize( 300, 300 ); frame.setVisible( true );
Thread.sleep(5000);
4
for(int i = start; i >= 0; i--) { label.setText( Integer.toString(i) ); Thread.sleep(500); }
label.setText("Kaboom!"); Thread.sleep(5000);
} catch ( InterruptedException e ) { System.out.println("Oh look! an exception!"); } } }
// This is the "real" main program. Static methods cannot // invoke non-static methods... public void doThis() { Window1 w1 = new Window1(13); w1.run(); System.out.println("Ok, I'm done."); System.exit(0); }
/// Entry point. Just create an object and call doThis(). public static void main( String[] args ) {
Counter02 obj = new Counter02(); obj.doThis(); }
}
Counter03o creates two windows doing the same thing, but one is different than the
other.o uses Runnableo uses join as a collective stop sign
one will wait for the other before proceeding
Counter03.java/* File: Counter03.java
Continuing from Counter02, now we make the private inner class "Runnable". Using threads, we can open two windows both counting down. Calls to Thread.sleep() ensure that the two count downs run concurrently.
5
*/
import javax.swing.*;import java.awt.Font;
public class Counter03 {
private class Window1 implements Runnable {
int start = 10; // by default, count down from 10 int xpos = 0; // window position int ypos = 0; // window position
Window1() { } // do nothing, use default values
Window1(int n) { start = n; } // count down from n
Window1(int n, int x, int y) { start = n; // set all parameters xpos = x; ypos = y; }
public void run() {
try {
// same old, same old, except we pick a window position JFrame frame = new JFrame( "Start value =" + start ); JLabel label = new JLabel("Hello, Java!", JLabel.CENTER ); label.setFont( new Font("Serif", Font.BOLD, 36) ); frame.getContentPane().add( label ); frame.setSize( 300, 300 ); frame.setLocation( xpos, ypos ); // pick window position frame.setVisible( true );
Thread.sleep(1000);
for(int i = start; i >= 0; i--) { label.setText( Integer.toString(i) ); Thread.sleep(2000); }
label.setText("Kaboom!"); Thread.sleep(1000);
} catch ( InterruptedException e ) {
6
System.out.println("Oh look! an exception!"); } } }
// This time we make two windows public void doThis() { Window1 w1 = new Window1(13); Thread t1 = new Thread(w1); t1.start();
Window1 w2 = new Window1(9, 400, 0); Thread t2 = new Thread(w2); t2.start();
// don't quit until both windows have stopped running try { t1.join(); // wait for w1 to stop t2.join(); // wait for w2 to stop
} catch ( InterruptedException e ) { System.out.println("Oh look! an exception!"); }
System.exit(0); }
public static void main( String[] args ) {
Counter03 obj = new Counter03(); obj.doThis(); }}
Counter04o showing how threads can access data/member variables
values are pulled from “sharedArray” to display to the screeno also show how threads may not access that data synchronously
even though “joined”o rest of code is the same as Counter03
Counter04.java/* File: Counter04.java
7
This time the Counter class has an int array called sharedArray[].
Methods in private inner classes have access to sharedArray[]. Both threads can read from and write to sharedArray.
Instead of counting down 10, 9, 8, ... as before, the threads print out values from sharedArray[].
Twist: whichever thread finishes first, trashes the array (by storing negative values in the array) so the other thread prints out "garbage".
*/
import javax.swing.*;import java.awt.Font;
public class Counter04 {
// data members are accessible to methods of inner classes. int [] sharedArray;
private class Window1 implements Runnable {
int start = 10; int xpos = 0; int ypos = 0;
Window1() { } // do nothing, use default values
Window1(int n) { start = n; } // count down from n
Window1(int n, int x, int y) { start = n; // set all parameters xpos = x; ypos = y; }
public void run() {
try {
// same old, same old JFrame frame = new JFrame( "Start value =" + start ); JLabel label = new JLabel("Hello, Java!", JLabel.CENTER ); label.setFont( new Font("Serif", Font.BOLD, 36) ); frame.getContentPane().add( label ); frame.setSize( 300, 300 ); frame.setLocation( xpos, ypos ); frame.setVisible( true );
Thread.sleep(1000);
8
// print from array instead of printing i .. for(int i = start; i >= 0; i--) { label.setText( Integer.toString(sharedArray[i]) ); Thread.sleep(2000); }
label.setText("Kaboom!");
// when we are done, trash the array. No call to // Thread.sleep(), so this is really fast. for (int i = 0; i < sharedArray.length; i++) { sharedArray[i] = -i; }
Thread.sleep(1000);
} catch ( InterruptedException e ) { System.out.println("Oh look! an exception!"); } } }
public void doThis() { // initialize sharedArray... sharedArray = new int[100];
for (int i = 0; i < sharedArray.length; i++) { sharedArray[i] = 3 * i; }
// same as before Window1 w1 = new Window1(13); Thread t1 = new Thread(w1); t1.start() ;
Window1 w2 = new Window1(9, 400, 0); Thread t2 = new Thread(w2); t2.start() ;
try { t1.join(); t2.join(); } catch ( InterruptedException e ) { System.out.println("Oh look! an exception!"); } System.exit(0); }
public static void main( String[] args ) {
Counter04 obj = new Counter04(); obj.doThis();
9
}}
Counter05o using two distinct Threads (in separate classes) to access data
w1 (Counter Thread) displays values from the shared array
w2 (Sequence Thread) enters Fibonacci values into the shared array
Counter05 and Counter06 UML-ishput pic here of overall setup
o after one thread has completed (w2), stops the other thread (w1)o synchronization becomes an issue (and a topic)o in action
Counter05.java/* File: Counter05.java
Continuing along the same theme, now the two windows are written on by two different classes. One thread tries to populate the sharedArray with sequences (squares, Fibonacci numbers). The other thread just prints out whatever is in the array. Unfortunately, the first thread is slower (has larger sleep values) than the second thread. So, the second thread ends up printing out values before the array is ready.
Moral of the story: we need synchronization.*/
import javax.swing.*;import java.awt.Font;
public class Counter05 {
// data members are accessible to methods of inner classes. int [] sharedArray;
// These windows just print out the contents of sharedArray // over and over again. private class Window1 implements Runnable {
// similar set up as usual JFrame frame = new JFrame( "Sequence Window"); JLabel label = new JLabel("Hello, Java!", JLabel.CENTER ); label.setFont( new Font("Serif", Font.BOLD, 18) ); frame.getContentPane().add( label ); frame.setSize( 600, 300 ); // a bit wider frame.setLocation( xpos, ypos ); frame.setVisible( true );
Thread.sleep(1000);
// Write square values (0, 1, 4, 9, 16 ...) to sharedArray[] for(int i = 0; i < sharedArray.length; i++) { sharedArray[i] = i*i; // i squared label.setText( "Setting sharedArray[" + i + "] to " + i*i); Thread.sleep(2000); }
label.setText( "Done with Squares!" ); Thread.sleep(2000); // wait a bit
// Write Fibonacci numbers to sharedArray[] sharedArray[0] = 1; // base cases sharedArray[1] = 1;
for(int i = 2; i < sharedArray.length; i++) { sharedArray[i] = sharedArray[i-1] + sharedArray[i-2]; label.setText( "Setting sharedArray[" + i + "] to " + sharedArray[i]); Thread.sleep(2000); } label.setText( "Done with Fibonacci numbers!" );
Thread.sleep(2000); // wait a bit
} catch ( InterruptedException e ) { System.out.println("Oh look! an exception!"); } } }
12
public void doThis() {
// initialize sharedArray with "boring" numbers sharedArray = new int[20];
for (int i = 0; i < sharedArray.length; i++) { sharedArray[i] = i; }
// start window that prints out sharedArray[] Window1 w1 = new Window1(); Thread t1 = new Thread(w1); t1.start();
// start window that populates sharedArray[] with sequences SequenceWindow w2 = new SequenceWindow(400, 0); Thread t2 = new Thread(w2); t2.start();
try { t2.join(); // wait for sequences to stop
w1.keepRunning = false; // tell w1 to stop
t1.join(); // wait for w1 to stop
} catch ( InterruptedException e ) { System.out.println("Oh look! an exception!"); }
System.exit(0); }
public static void main( String[] args ) {
Counter05 obj = new Counter05(); obj.doThis(); }}
Counter06o synchronizes writing/displaying of array data
look for key word synchronized remember this will BLOCK any other process for accessing this
resourceo first time through, SequenceWindow, writes squared values in the shared
arrayo in action
13
Counter06.java/* File: Counter06.java Synchronized version of Counter05. Now the threads are well behaved. The display thread cannot print out the array before it first thread is done populating the entire array. Also, the first thread cannot start populating the array with Fibonacci numbers until the second thread is done showing the squares. Everything proceeds nicely in lock step.*/
import javax.swing.*;import java.awt.Font;
public class Counter06 {
// data members are accessible to methods of inner classes. int [] sharedArray;
// These windows just print out the contents of sharedArray // over and over again. private class Window1 implements Runnable {
int xpos = 0; int ypos = 0; boolean keepRunning; // keep going?
// similar set up as usual JFrame frame = new JFrame( "Sequence Window"); JLabel label = new JLabel("Hello, Java!", JLabel.CENTER ); label.setFont( new Font("Serif", Font.BOLD, 18) ); frame.getContentPane().add( label ); frame.setSize( 600, 300 ); // a bit wider frame.setLocation( xpos, ypos ); frame.setVisible( true );
Thread.sleep(1000); // let other window go first
15
// Write square values (0, 1, 4, 9, 16 ...) to sharedArray[] // This time it is synchronized. synchronized( sharedArray ) { for(int i = 0; i < sharedArray.length; i++) { sharedArray[i] = i*i; // i squared label.setText( "Setting sharedArray[" + i + "] to " + i*i); Thread.sleep(500); } } // end of synchronized
label.setText( "Done with Squares!" ); Thread.sleep(2000); // wait a bit
// Write Fibonacci numbers to sharedArray[] // This time it is synchronized. synchronized( sharedArray ) { sharedArray[0] = 1; // base cases sharedArray[1] = 1;
for(int i = 2; i < sharedArray.length; i++) { sharedArray[i] = sharedArray[i-1] + sharedArray[i-2]; label.setText( "Setting sharedArray[" + i + "] to " + sharedArray[i]); Thread.sleep(500); }
} // end of synchronized( sharedArray )
label.setText( "Done with Fibonacci numbers!" );
Thread.sleep(2000); // wait a bit
} catch ( InterruptedException e ) { System.out.println("Oh look! an exception!"); } } }
public void doThis() {
// initialize sharedArray with "boring" numbers sharedArray = new int[20];
for (int i = 0; i < sharedArray.length; i++) { sharedArray[i] = i; }
// start window that prints out sharedArray[] Window1 w1 = new Window1(400, 75); Thread t1 = new Thread(w1); t1.start() ;
16
// start window that populates sharedArray[] with sequences SequenceWindow w2 = new SequenceWindow(400, 300); Thread t2 = new Thread(w2); t2.start() ;
try {
t2.join(); // wait for sequences to stop
w1.keepRunning = false; // tell w1 to stop
t1.join(); // wait for w1 to stop
} catch ( InterruptedException e ) { System.out.println("Oh look! an exception!"); }
System.exit(0); }
public static void main( String[] args ) {
Counter06 obj = new Counter06(); obj.doThis(); }}
17
start() vs. run() vs. join() start
o comes firsto preps the threado does not run the threado calls run()o return back to this call when all is done
unless a join is used, then ends there run
o runs the threado preps (starts) the thread if start not called
joino allows one thread to wait for the completion of anothero some threads may end early, but the complete finish won’t happen until
the other joined threads are completeo blocks threads together in time
while ( itr.hasNext() ) { qStr += String.format("[%2d]", itr.next()); }
for (int i = q.size(); i < limit; i++) { qStr += "[xx]";}
return qStr; }
// For Thread object to start public void run() { try {
// Set up a frame in Swing as usual JFrame frame = new JFrame( "The Buffer"); JLabel label = new JLabel(toString(), JLabel.CENTER ); label.setVerticalTextPosition(JLabel.TOP); label.setFont( new Font("Monospaced", Font.BOLD, 24) ); frame.getContentPane().add( label ); frame.setSize( 800, 150 ); frame.setLocation( xpos, ypos );
20
frame.setVisible( true );
keepRunning = true;
// keep showing contents of the FIFO queue until // someone says stop. while (keepRunning) { label.setText( toString() ); // toString() is synched Thread.sleep(50); }
} catch ( InterruptedException e ) { System.out.println("Oh look! an exception!"); } }}
Version 2o same overall setupo The Producer is running faster than the Consumer.
producer is producing numbers from 3 up consumer is checking if the number it is looking at is prime
o It fills up the buffer and some numbers get dropped or not entered into the buffer since full
o in action
Version 3o same overall setupo The Producer is running faster AT FIRST than the Consumer.
producer stops since the buffer is full isFull function()
consumer is checking if the number it is looking at is prime producer will add when buffer not full
o It fills up the buffer and some numbers get dropped or not entered into the buffer since full
o in action
Version 4o same overall setupo This version uses wait and notify (they are in the Buffer class).
Setups (Runnable vs. Thread) notice in either case, start() is not a declared method Runnable
o base class extends Runnableo create a Thread using the base class as a valueo uses start() to call run() function
by default looks for run() do not need to call run() specifically remember start() has its own distinct set of features and items it
takes care of
Setting up a Runnable Class and Thread
// Set up producer thread Producer prod; // Pass on buffer reference. Set window position prod = new Producer(buf, 450, 0); Thread prodThread = new Thread(prod); prodThread.start();
Threado base class extends Thread
Setting up a Thread Class and local Thread
A t1=new A(); // Threaded class name was At1.start();
23
I/O Threads and Blocking and Scheduling Thread Scheduling
o the thread able to run with the highest priority is activeo in Java, if a higher thread is sleeping, and wakes up, any lower priority
threads then sleeps Blocking Threads
o a thread may want to be blocked (suspended) if it cannot read input (or lacks input to continue)
o this allows other threads to begino will wake when I/O becomes available
Starvationo happens when a high priority threads never blocks or stopso all other threads starve since they never run/finish
race conditionso two or more threads accessing and modifying a single objecto both are racing to store their data
Lockso synchronize keywordo only one thread can access a resource at a timeo java.util.concurrent
Lock interface ReentrantLock
Priority Coding Strategies
Bad Things that can happen with Threads
24
Handling Interrupts if thread is in sleeping or waiting state
o sleep() or wait() is invokedo interrupt breaks out the sleeping or waiting state throwing
InterruptedException. if thread is not in the sleeping or waiting state
o interrupt() performs normal behavior and doesn't interrupt the thread but sets the interrupt flag to true
an interrupt is usually called where the thread is startedo t1.start()o unless the thread is passed somewhere
can only be interrupted AFTER started it is up to the programmer on exactly what the thread does when interrupted
o within the RUN(), the catch dictates what happens to the threado usually it terminates
the thread needs to be alive when interruptedo the timing of when the thread is interrupted should be checked
25
Thread not interrupted in time/* * Here a thread is started and ends SO FAST that t1.interrupt() is useless. * You can tell since the "Thread interrupted ..." does not show up in our input */
class A extends Thread{
public void run(){
System.out.println("running thread");
try{
Thread.sleep(1000);System.out.println("task");
}catch(InterruptedException e){throw new RuntimeException("Thread interrupted..."+e+"\n");
}
}
public static void main(String args[]){A t1=new A();t1.start();
try{sleep(10000);System.out.println("Done waiting to interrupt!");t1.interrupt();
Outputrunning threadtaskDone waiting to interrupt!But think of it as
26
27
Thread interrupted in time/* Here there is nothing to block the thread AS SOON as it was * created. Hence it will use the exception InterruptedException */class A extends Thread{
public void run(){
System.out.println("got here");try{
Thread.sleep(1000);System.out.println("got here 2");
}catch(InterruptedException e){throw new RuntimeException("Thread interrupted..."+e);
}
}
public static void main(String args[]){A t1=new A();t1.start();try{
OutputException in thread "Thread-0" got herejava.lang.RuntimeException: Thread interrupted...java.lang.InterruptedException: sleep interrupted
at A.run(A.java:12)
Notice it at LEAST got to run(), and in at least one line inside runBut think of it as this
28
Thread interrupted but still runs afterwardsclass A2 extends Thread{
public void run(){
System.out.println("got here");try{
Thread.sleep(1000);System.out.println("got here 2");
}catch(InterruptedException e){System.out.println("Exception handled "+e);// but nothing here to stop it!!// a return or Throw would stop this runaway thread!!
}System.out.println("thread is running...");
}
public static void main(String args[]){A2 t1=new A2();t1.start();
t1.interrupt();
System.out.println("got here 3");
}}
Outputgot here 3got hereException handled java.lang.InterruptedException: sleep interruptedthread is running...
29
Interrupting twice (to reactivate the thread)class A2 extends Thread{
Outputgot hereException handled java.lang.InterruptedException: sleep interruptedsleeping for a whilegot here 3java.lang.InterruptedException: sleep interruptedOut of Interruptthread is running...
at java.lang.Thread.sleep(Native Method)at A2.run(A2.java:13)
finished
30
Determining if a Thread has been interruptedclass A3 extends Thread{
public void run(){for(int i=1;i<=5;i++){
System.out.println(i);if(Thread.interrupted()){
System.out.println("code for interrupted thread");}
}}
public static void main(String args[]){A3 t1=new A3();t1.start();
t1.interrupt();
}}
Output1code for interrupted thread2345
Handling thread exceptions
31
SourcesCSCE3193: Programming Paradigms (Dr. Banerjee) SlidesDr. Richard Chang - UMBChttp://www.javabeginner.com/learn-java/java-threads-tutorialhttp://www.cs.usfca.edu/~parrt/course/601/lectures/threads.htmlhttp://www.javamex.com/tutorials/threads/http://docs.oracle.com/javase/tutorial/essential/concurrency/threads.html