20
slide 8.1 nced Programming 2004, based on LY Stefanus’s slides Multithreading: Thread Scheduling ThreadGroup

Advanced Programming 2004, based on LY Stefanus’s slides slide 8.1 Multithreading : Thread Scheduling ThreadGroup

Embed Size (px)

Citation preview

Page 1: Advanced Programming 2004, based on LY Stefanus’s slides slide 8.1 Multithreading : Thread Scheduling ThreadGroup

slide 8.1Advanced Programming 2004, based on LY Stefanus’s slides

Multithreading:Thread Scheduling

ThreadGroup

Page 2: Advanced Programming 2004, based on LY Stefanus’s slides slide 8.1 Multithreading : Thread Scheduling ThreadGroup

slide 8.2Advanced Programming 2004, based on LY Stefanus’s slides

Thread Scheduling

• On a system with N available processors, we will usually see N of the highest-priority runnable threads executing.

• Lower-priority threads are guaranteed to run only when higher-priority threads are blocked (not runnable). Lower-priority threads might run at other times to prevent starvation, but we cannot rely on it.

• A thread is blocked if it is waiting or executing any other system or thread function that is blocked. When a thread blocks, Java picks the highest-priority runnable thread (or one of those with the highest priority if there is more than one thread at that priority) and lets it run.

• A thread’s priority is initially the same as the priority of the thread that created it. The priority can be changed using the method setPriority with a value between the Thread’s constants MIN_PRIORITY and MAX_PRIORITY. The default priority is NORM_PRIORITY. The method getPriority returns the priority of a thread.

Page 3: Advanced Programming 2004, based on LY Stefanus’s slides slide 8.1 Multithreading : Thread Scheduling ThreadGroup

slide 8.3Advanced Programming 2004, based on LY Stefanus’s slides

public static void yield( )

• This method causes the currently executing thread to yield so that any other runnable threads can run.

• The thread scheduler chooses a thread to run from the runnable threads. The thread that is picked can be the one that yielded, because it may be the highest-priority runnable thread.

• The following example shows how yield works. The program takes a list of words as arguments and creates a thread that is responsible for printing each word.

Page 4: Advanced Programming 2004, based on LY Stefanus’s slides slide 8.1 Multithreading : Thread Scheduling ThreadGroup

slide 8.4Advanced Programming 2004, based on LY Stefanus’s slides

public class Babble extends Thread { static boolean doYield; //yield to other threads? static int howOften; //how many times to print? private String word; //word to print

Babble( String whatToSay ) { word = whatToSay; }

public void run( ) { for (int i=0; i < howOften; i++) { System.out.println(word); if (doYield) yield(); //give another thread a chance } }

Page 5: Advanced Programming 2004, based on LY Stefanus’s slides slide 8.1 Multithreading : Thread Scheduling ThreadGroup

slide 8.5Advanced Programming 2004, based on LY Stefanus’s slides

public static void main( String[] args ) { doYield = new Boolean(args[0]).booleanValue(); howOften = Integer.parseInt(args[1]);

//create a thread for each word at max priority Thread cur = currentThread(); cur.setPriority(Thread.MAX_PRIORITY); for (int i = 2; i< args.length; i++) { new Babble(args[i]).start(); } }}

Page 6: Advanced Programming 2004, based on LY Stefanus’s slides slide 8.1 Multithreading : Thread Scheduling ThreadGroup

slide 8.6Advanced Programming 2004, based on LY Stefanus’s slides

• When the threads do not yield, each thread gets large chunks of time, usually enough to finish all the prints without any other thread getting CPU cycles.

• For example (likely output):

>> java Babble false 2 Yes NoWayYesYesNoWayNoWay>> java Babble true 2 Yes NoWayYesNoWayYesNoWay

Page 7: Advanced Programming 2004, based on LY Stefanus’s slides slide 8.1 Multithreading : Thread Scheduling ThreadGroup

slide 8.7Advanced Programming 2004, based on LY Stefanus’s slides

User Threads & Daemon Threads

• Each application starts with one thread – the one that executes main. If the application creates no other threads, it will finish when main returns. But if the application creates other threads, what happens to them when main returns?

• There are two kinds of threads: user and daemon. The presence of a user thread keeps the application running, whereas a daemon thread is expendable.

• When the last user thread is finished, any daemon threads are stopped and the application is finished.

• The status of a new thread is inherited from the thread that creates the new thread and cannot be changed after the new thread is started.

• Use the method setDaemon(true) to mark a thread as a daemon thread before it is started, and use isDaemon( ) to test that flag.

Page 8: Advanced Programming 2004, based on LY Stefanus’s slides slide 8.1 Multithreading : Thread Scheduling ThreadGroup

slide 8.8Advanced Programming 2004, based on LY Stefanus’s slides

• If your main method spawns a thread, that thread inherits the user-thread status of the original thread.

• If you want your application to exit when the original thread dies, you mark all the threads you create as daemon threads.

• Daemon threads run for benefit of other threads.

• Garbage collector is a daemon thread.

Page 9: Advanced Programming 2004, based on LY Stefanus’s slides slide 8.1 Multithreading : Thread Scheduling ThreadGroup

slide 8.9Advanced Programming 2004, based on LY Stefanus’s slides

volatile

• If multiple threads could potentially modify a variable, you should mark it as volatile.

• For example, if you had a value that was continuously displayed by a graphics thread and that could be changed by non-synchronized methods, the display code might look something like this: int currentValue = 123; for (;;) { display.showValue(currentValue); Thread.sleep(1000); }

• If there is no way for showValue to change the value of currentValue, the compiler might assume that it can treat currentValue as unchanged inside the loop and simply use the constant 123 each time it invokes showValue.

• But if currentValue is a variable that is updated by other threads while the loop is running, the compiler’s assumption would be wrong.

Page 10: Advanced Programming 2004, based on LY Stefanus’s slides slide 8.1 Multithreading : Thread Scheduling ThreadGroup

slide 8.10Advanced Programming 2004, based on LY Stefanus’s slides

• Declaring the variable currentValue to be volatile prevents the compiler from making such assumptions, forcing it to reread the value on every iteration of the loop.

volatile int currentValue = 123; for (;;) { display.showValue(currentValue); Thread.sleep(1000); }

Page 11: Advanced Programming 2004, based on LY Stefanus’s slides slide 8.1 Multithreading : Thread Scheduling ThreadGroup

slide 8.11Advanced Programming 2004, based on LY Stefanus’s slides

Waiting for a Thread to Finish

• One thread can wait for another thread to finish using the method join.

• See the Java documentation for details.

Page 12: Advanced Programming 2004, based on LY Stefanus’s slides slide 8.1 Multithreading : Thread Scheduling ThreadGroup

slide 8.12Advanced Programming 2004, based on LY Stefanus’s slides

public class ShowJoin { public static void main( String[] args ) { WorkingThread wt = new WorkingThread(); wt.start(); //do something else for (int i=1; i <= 100; i++) System.out.print("*"); try { wt.join(); System.out.println("Result is " + wt.getResult()); } catch (InterruptedException ie) { System.out.println("No result: interrupted"); } }}

Page 13: Advanced Programming 2004, based on LY Stefanus’s slides slide 8.1 Multithreading : Thread Scheduling ThreadGroup

slide 8.13Advanced Programming 2004, based on LY Stefanus’s slides

class WorkingThread extends Thread { private long result; public void run() { result = calculate(40); } public long getResult() { return result; } //calculate the n-th Fibonacci number public long calculate(int n) { if (n == 0 || n == 1) return n; else return calculate(n-1) + calculate(n-2); }}

Page 14: Advanced Programming 2004, based on LY Stefanus’s slides slide 8.1 Multithreading : Thread Scheduling ThreadGroup

slide 8.14Advanced Programming 2004, based on LY Stefanus’s slides

Page 15: Advanced Programming 2004, based on LY Stefanus’s slides slide 8.1 Multithreading : Thread Scheduling ThreadGroup

slide 8.15Advanced Programming 2004, based on LY Stefanus’s slides

Exercise

• What happens if

wt.join( )

is replaced by

Thread.sleep(500)?

Page 16: Advanced Programming 2004, based on LY Stefanus’s slides slide 8.1 Multithreading : Thread Scheduling ThreadGroup

slide 8.16Advanced Programming 2004, based on LY Stefanus’s slides

Thread Groups

• Threads are put into thread groups for security reasons.

• A thread group can be contained within another thread group, providing a hierarchy.

• Threads within a thread group can modify the other threads in the group, including any threads farther down the hierarchy.

• A thread cannot modify threads outside its own group. This restriction can be used to protect threads from manipulation by other threads.

Page 17: Advanced Programming 2004, based on LY Stefanus’s slides slide 8.1 Multithreading : Thread Scheduling ThreadGroup

slide 8.17Advanced Programming 2004, based on LY Stefanus’s slides

• Every thread belongs to a thread group. Each thread group is represented by a ThreadGroup object.

• We can specify the thread group in the thread constructor; the default is to place each new thread in the same thread group as that of the thread that created it.

• When a thread dies, the Thread object is removed from its group.

• See the Java documentation for details.

Page 18: Advanced Programming 2004, based on LY Stefanus’s slides slide 8.1 Multithreading : Thread Scheduling ThreadGroup

slide 8.18Advanced Programming 2004, based on LY Stefanus’s slides

• Thread groups can be daemon groups.• A daemon threadgroup is automatically destroyed

when it becomes empty.• Setting a threadgroup to be a daemon group does

not affect whether any thread or group contained in that group is a daemon or not. It affects only what happens when the group becomes empty.

• We can use a threadgroup to manage threads in the group.

Page 19: Advanced Programming 2004, based on LY Stefanus’s slides slide 8.1 Multithreading : Thread Scheduling ThreadGroup

slide 8.19Advanced Programming 2004, based on LY Stefanus’s slides

Exit Safely

• The following example interrupts all threads in the current group, lets them finish, and then invokes exit:

public static void safeExit( int status ) { //Get the list of all threads Thread myThread = Thread.currentThread(); ThreadGroup thisGroup = myThread.getThreadGroup(); int count = thisGroup.activeCount(); Thread[] threads = new Thread[count + 20]; //+20 for slop thisGroup.enumerate(threads); //Interrupt all threads for (int i = 0; i < threads.length; i++) { if (threads[i] != null && threads[i] != myThread) threads[i].interrupt(); }

Page 20: Advanced Programming 2004, based on LY Stefanus’s slides slide 8.1 Multithreading : Thread Scheduling ThreadGroup

slide 8.20Advanced Programming 2004, based on LY Stefanus’s slides

//Wait for all threads to finish for (int i = 0; i < threads.length; i++) { if (threads[i] != null && threads[i] != myThread) { try { threads[i].join(); } catch (InterruptedException ie) { } } }

//Now we can exit System.exit(status);}

• Note that when we invoke exit, the JVM will simply stop.