Java Threads
Resources
Course textbook: pp. 162-165 Java Threads by Scott Oaks & Henry Wong (OReilly) API docs
http://download.oracle.com/javase/6/docs/api/ java.lang.Thread, java.lang.Runnable java.lang.Object, java.util.concurrent
Tutorials
http://download.oracle.com/javase/tutorial/essential/concurrency/index.html http://download.oracle.com/javase/tutorial/essential/concurrency/procthread.html
Introduction to Java Threads
http://www.javaworld.com/javaworld/jw-04-1996/jw-04-threads.html
Thread safety
http://en.wikipedia.org/wiki/Thread-safety
http://www.javaworld.com/jw-08-1998/jw-08-techniques.html
1
Coverage
Thread class
run, start methods yield, join sleep
Synchronization
synchronized methods & objects wait/notify/notifyAll conditions
2
java.lang.Thread
Two techniques to create threads in java 1) implementing the Runnable interface
The Runnable interface should be implemented by any class whose instances are intended to be executed by a thread. The class must define a method, called run, with no arguments. invoke Thread constructor with an instance of this Runnable class See pages 162 and 164 in text for an example
2) extending Thread
Define a subclass of java.lang.Thread
Define a run method
In another thread (e.g., the main), create an instance of the Thread subclass
Then, call start method of that instance
3
Example 1
Create 2 threads from the Main, then start them Threads will be instances of different thread sub-classes
class MyThreadA extends Thread { public void run() { // entry point for thread for (;;) { System.out.println("hello world1"); } } }
class MyThreadB extends Thread { public void run() { // entry point for thread for (;;) { System.out.println("hello world2"); } } }
public class Main1 { public static void main(String [] args) { MyThreadA t1 = new MyThreadA(); MyThreadB t2 = new MyThreadB(); t1.start(); t2.start();
// main terminates, but in Java the other threads keep running // and hence Java program continues running
} }
5
hello world2 hello world2 hello world1 hello world2 hello world1 hello world2 hello world2 hello world1 hello world1 hello world1 hello world1 hello world2 hello world1 hello world1 hello world2 hello world2 hello world1 hello world1 hello world2 hello world2 hello world1 hello world1 hello world2
Example 2
Create 2 threads from the Main, then start them Threads will be instances of the same thread sub-class Use argument of constructor of new thread class to pass text name of thread, e.g., thread1 and thread2
Data member provides different data per thread (i.e., then name) A data member can also be used to share data
7
class MyThread extends Thread { private String name; public MyThread(String name) { this.name = name; }
public void run() { for (;;) { System.out.println(name + ": hello world"); } }
} public class Main2 { public static void main(String [] args) { MyThread t1 = new MyThread("thread1"); MyThread t2 = new MyThread("thread2"); t1.start(); t2.start(); } }
8
thread2: hello world thread2: hello world thread2: hello world thread2: hello world thread2: hello world thread2: hello world thread2: hello world thread2: hello world thread2: hello world thread2: hello world thread2: hello world thread2: hello world thread2: hello world thread2: hello world thread2: hello world thread1: hello world thread2: hello world thread1: hello world thread2: hello world thread2: hello world thread1: hello world thread2: hello world thread2: hello world
See the variation in output: This variation in output is called a race condition (often race conditions are bugs in programs)
java.lang.Thread
public static void yield();
Method of java.lang.Thread Thread gives up CPU for other threads ready to run
10
class MyThread extends Thread { private String name; public MyThread(String name) { this.name = name; }
public void run() { for (;;) { System.out.println(name + ": hello world"); yield(); } }
} public class Main3 { public static void main(String [] args) { MyThread t1 = new MyThread("thread1"); MyThread t2 = new MyThread("thread2"); t1.start(); t2.start(); } }
11
thread1: hello world thread2: hello world thread1: hello world thread2: hello world thread1: hello world thread2: hello world thread1: hello world thread2: hello world thread1: hello world thread2: hello world thread1: hello world thread2: hello world thread1: hello world thread2: hello world thread1: hello world thread2: hello world thread1: hello world thread2: hello world thread1: hello world thread2: hello world thread1: hello world thread2: hello world thread1: hello world
Some Output
Notice the alternation of output
12
More Thread Members: join
public final void join();
MyThread t1 = new MyThread("thread1"); t1.start(); t1.join(); Wait until the thread is not alive Threads that have completed are not alive as are threads that have not yet been started
public static void sleep (long millis) throws InterruptedException;
Makes the currently running thread sleep (block) for a period of time The thread does not lose ownership of any monitors. InterruptedException - if another thread has interrupted the current thread.
13
Join Example
14
hello world1 hello world1 hello world1 hello world1 hello world1 hello world1 hello world1 hello world1 hello world1 hello world1 hello world1 hello world1 hello world1 hello world1 hello world1 hello world1 hello world1 hello world1 hello world1 hello world1 hello world1 Thread is done!
Some output
15
Thread State
public Thread.State getState()
Returns the state of this thread. This method is designed for use in monitoring of the system state, not for synchronization control
http://java.sun.com/javase/6/docs/api/java/lang/Thread.State.html
Thread Scheduling in Java
public final void setPriority(int newPriority); public final int getPriority(); public static final int MAX_PRIORITY
// on my system: 10; Mac OS X 2/21/05
public static final int MIN_PRIORITY
// on my system: 1; Mac OS X 2/21/05
Scheduling
Priority inherited from parent, but can be changed Higher priority threads generally run before lower priority threads For equal priority threads, best to call yield() intermittently to handle JVMs with user-level threading (i.e., no time-slicing)
17
Sharing Data Across Java Threads
Consider the situation where a parent thread wants to pass data to a child thread
e.g., so that child can change data and parent can have access to the changed data
How can this be done? Can pass an object instance to the child thread constructor, and retain that object instance in a data member
18
class SharedData { public int a = 0; public String s = null; public SharedData() { a = 10; s = "Test"; } } class MyThread extends Thread { private SharedData m_data = null; public MyThread(SharedData data) { m_data = data; }
public void run() { for (;;) {
m_data.a++; } } }
19
public class Main5 { public static void main(String [] args) { SharedData data = new SharedData(); MyThread t1 = new MyThread(data); t1.start(); for (;;) { data.a--; } } }
If we have multiple threads accessing this shared data, how do we synchronize access to ensure it remains in a consistent state? 20
Basic Tools for Synchronization in Java
Synchronized methods Synchronized objects Methods
wait notify notifyAll
Also should talk about condition variables in Java
21
Synchronized Methods: Monitors
synchronized keyword used with a method
E.g.,
public synchronized void SetValue() { // Update instance data structure. // When the thread executes here, it exclusively has the monitor lock }
Provides instance-based mutual exclusion
A lock is implicitly provided-- allows at most one thread to be executing the method at one time
Used on a per method basis; not all methods in a class have to have this
But, youll need to design it right!!
22
Difference: Synchronized vs. Non-synchronized
Class with synchronized methods
How many threads can access the methods of an object?
Class with no synchronized methods
How many threads can access the methods of an object?
23
Example
Construct a queue (FIFO) data structure that can be used by two threads to access the queue data in a synchronized manner
Producer thread: Adds data into queue Consumer thread: Removes data from queu
For one instance of the queue, only one thread should be able to modify the queue, i.e., we should have mutual exclusion on methods of one instance of the queue
24
25
http://www.cprince.com/courses/cs5631/lectures/JavaThreads/SynchMainGeneric.java
26
http://www.cprince.com/courses/cs5631/lectures/JavaThreads/SynchMainGeneric.java
27
http://www.cprince.com/courses/cs5631/lectures/JavaThreads/SynchMainGeneric.java
28
http://www.cprince.com/courses/cs5631/lectures/JavaThreads/SynchMainGeneric.java
Lets run this and see what happens
29
30
Ooops! What happened?
31
This implementation has a problem! The Consumer prints, which slows it down a LOT, and thus the producer is faster, and thus the producer fills up the queue, and causes heap space to run out!! This is a kind of race condition
The results depend on the speed of execution of the two processes
Would like to alter this program to limit the maximum number of items that are stored in the queue. Goal: have the producer block (wait) when 32 the queue reaches some fixed size limit
Also
Better to have the Remove block (wait) when the queue is empty I.e., presently we are doing a busy wait (also called polling) We are repeatedly checking the queue to see if it has data, and using up too much CPU time doing this
33
wait method (see also java.lang.Object)
Does a blocking (not busy) wait Relative to an Object
E.g., Used within a synchronized method
Releases lock on Object and waits until a condition is true
Blocks calling process until notify() or notifyAll() is called on same object instance (or exception occurs)
Typically used within a loop to re-check a condition wait(long millis); // bounded wait
34
notify and notifyAll methods (see also java.lang.Object)
Stop a process from waiting wakes it up Relative to an Object
E.g., Used within a synchronized method
Wakes up a blocked thread (notify) or all blocked threads (notifyAll)
One woken thread reacquires lock; The awakened thread will not be able to proceed until the current thread relinquishes the lock on this object.
For notify, if more than one thread available to be woken, then one is picked
35
Typical use of wait within a synchronized method
while (condition not true) { try { wait(); // this.wait(); } catch { System.out.println(Interrupted!); } } // After loop, condition now true & thread // has monitor lock for this object instance
Example
Extend the example from before:
a queue (FIFO) data structure that can be used by two threads to access the queue data in a synchronized manner
This time, use wait & notify to block the Producer thread if the queue is full, and block Consumer thread if the queue is empty
37
Re-checking Monitor Conditions
wait/notify After receiving a notify, a process waiting on a condition may not be next to gain access to monitor (to the data) E.g., occurs if notifyAll used Process may need to re-check the conditions upon which it was waiting
An awakened thread will compete in the usual manner with any other threads that might be actively competing to synchronize on this object; for example, the awakened thread enjoys no reliable privilege or disadvantage in being the next thread to lock this object. 38 (http://java.sun.com/j2se/1.5.0/docs/api/)
InterruptedException
Wait can be woken by the exception, I.e., for reasons other than notify Sometimes this can be handled as part of the process of re-checking conditions There is another way to handle it too
39
Exception in Wait
// In a synchronized method // check your condition, e.g., with a semaphore // operation, test value member variable if /* or while */ (/* condition */) { boolean interrupted; do { interrupted = false; try { wait(); } catch (InterruptedException e) { interrupted = true; } } while (interrupted); }
Only allows release from wait caused by notify or notifyAll
40
Synchronized Blocks
Synchronized methods
Implicitly lock is on this object
Synchronized blocks
lock on an arbitrary, specified object similar to condition variables in monitors but need to have a synchronized block around an object before wait/notify used use wait/notify on the object itself
41
Syntax
synchronized (object) { // object.wait() // object.notify() // object.notifyAll() } For example, this allows you to synchronize just a few lines of code, or to synchronize on the basis of an arbitrary object
42
Another Example
Suppose in a Global File Table, suppose that per open file you keep an Object Lock; you can then use a synchronized block to make sure that some operations only get done in a mutually exclusive manner on the file synchronized (file[i].Lock) { // if we get to here were the only one // accessing file i 43 }
Conditions
Java interface:
http://download.oracle.com/javase/6/docs/api/java/util/concurrent/locks/Condition.html
Lets you have multiple independent wait events for a monitor So, have one monitor lock, but can wait within the monitor for more than one reason Use await/signal (not wait/notify) Also: Must have explicit lock (dont use synchronized keyword) Lock monitor as very first thing you do Unlock monitor as very last thing you do
44
END!
45
Lab 5: Agent Simulation
Could use synchronized blocks to accomplish synchronization on the environment cells synchronized (cell) { // check to see if agent can consume food // or socialize depending on what the goal // of the agent is }
46
Example
Implement Semaphore class with Java synchronization
Provide constructor, and P (wait) and V (signal) methods Use synchronized methods
and Java wait/notify
Note
Java implements Semaphores
http://java.sun.com/j2se/1.5.0/docs/api/java/util/concurrent/Semaphore.html
47
java.lang.Runnable Interface
The Runnable interface should be implemented by any class whose instances are intended to be executed by a thread. The class must define a method of no arguments called run. Known Implementing Classes:
AsyncBoxView.ChildState, FutureTask, RenderableImageProducer, Thread, TimerTask
From http://java.sun.com/j2se/1.5.0/docs/api/ Runnable can be used to create threads
See p.136-137 of text
48
END!
49
Example
Two producer threads (A & B), and one consumer thread Consumer needs one type of item from thread A and one type of item from thread B before it can proceed Use a loop and a wait and recheck conditions in the consumer
50
51
52
53
// only 1 thread can use Add or Remove at a time class SynchQueue { public LinkedList<Integer> l; SynchQueue () { l = new LinkedList<Integer>(); } public synchronized void Add(Integer elem) { l.addLast(elem); notify(); }
Blocking Remove
public synchronized Integer Remove() { while (l.size() == 0) { try { wait(); } catch (InterruptedException e) { System.out.println(ERROR: Thread interrupted!); } }
return l.removeFirst(); } } 54
55