9 - Threads

Réussis tes devoirs et examens dès maintenant avec Quizwiz!

Setting up thread priority FooRunnable r = new FooRunnable(); Thread t = new Thread(r); t.setPriority(8); t.start();

Although the default priority is 5, the Thread class has the three following constants (static final variables) that define the range of thread priorities: Thread.MIN_PRIORITY (1) Thread.NORM_PRIORITY (5) Thread.MAX_PRIORITY (10)

Exam Watch - The methods wait() , notify(), and notifyAll() are methods of only java.lang.Object, not of java.lang.Thread or java.lang.Runnable. Be sure you know which methods are defi ned in Thread, which in Object, and which in Runnable (just run(), so that's an easy one). Of the key methods in Thread, be sure you know which are static— sleep() and yield(), and which are not static—join() and start().

Class Object Class has foll methods - wait () notify() notifyAll() Class Thread Class has foll methods - start() yield() sleep() join() Interface Runnable has foll methods - run()

Waiting/blocked/sleeping - This is the state when its not eligible to run. These are 3 states but have one thing in common, its still alive but not eligible to run .i.e. not in runnable Dead - A thread is dead when its run() is completes.

EMPTY on PURPOSE

Synchronization & Locks - How does it work?

Every object in Java has an in built lock that comes into play when the object has synchronized method code.

The thread scheduler decides which thread—of all that are eligible—will actually run. When we say eligible, we really mean in the runnable state. Any thread in the runnable state can be chosen by the scheduler to be the one and only running thread. The order in which runnable threads are chosen to run is not guaranteed.

Exam Watch - Expect to see exam questions that look for your understanding of what is and is not guaranteed! You must be able to look at thread code and determine whether the output is guaranteed to run in a particular way or is indeterminate.

Once a thread completes its run() it ceases to a thread of execution. And the thread is considered as 'dead'

Exam Watch - In addition to using setName() and getName to identify threads, you might see getld(). The getld() method returns a positive, unique, long number, and that number will be that thread's only ID number for the thread's entire life.

Extending java.lang.Thread The simplest way to define code to run in a separate thread is to ■ Extend the java.lang.Thread class. ■ Override the run() method.

It looks like this: class MyThread extends Thread { public void run() { System.out.println("Important job running in MyThread");}}

Methods that help us influence the thread scheduling - Methods from the java.lang.Thread Class : public static void sleep(long millis) throws InterruptedException public static void yield() public final void join() throws InterruptedException public final void setPriority(int newPriority)

Methods from the java.lang.Object Class Every class in Java inherits the following three thread-related methods: public final void wait() throws InterruptedException public final void notify() public final void notifyAll()

A thread can only be in one of the 5 states - New Runnable Running Waiting/Blocked/Sleeping Dead

New - Its the state the thread is in after its instance is created but the start() is not invoked. The thread is not considered alive at this point Runnable - Here its considered alive. This is the state when its considered eligible to run, but not selected to be the running thread Running - This is where the actual action is, when the thread scheduler selects it from runnable pool to be the currently executing process ---contd on next card---

Thread Interaction The Object class has three methods, wait(), notify(), and notifyAll() that help threads communicate about the status of an event that the threads care about.

One key point to remember (and keep in mind for the exam) about wait/notify is this: wait(), notify(), and notifyAll() must be called from within a synchronized context! A thread can't invoke a wait or notify method on an object unless it owns that object's lock.

Remember - Once a thread has started, it can never be started again

Only a new thread can be started, and then only once. A runnable thread or a dead thread cannot be restarted.

Exam Watch - Just because a thread's sleep() expires, and it wakes up, does not mean it will return to running! Remember, when a thread wakes up, it simply goes back to the runnable state. So the time specifi ed in sleep() is the minimum duration in which the thread won't run, but it is not the exact duration in which the thread won't run. So you can't, for example, rely on the sleep() method to give you a perfectly accurate timer. Although in many applications using sleep() as a timer is certainly good enough, you must know that a sleep() time is not a guarantee that the thread will start running again as soon as the time expires and the thread wakes.

Remember that sleep() is a static method, so don't be fooled into thinking that one thread can put another thread to sleep. You can put sleep() code anywhere, since all code is being run by some thread. When the executing code (meaning the currently running thread's code) hits a sleep() call, it puts the currently running thread to sleep.

Exam watch There's nothing special about the run() method as far as Java is concerned. Like main(), it just happens to be the name (and signature) of the method that the new thread knows to invoke. So if you see code that calls the run() method on a Runnable (or even on a Thread instance), that's perfectly legal. But it doesn't mean the run() method will run in a separate thread! Calling a run() method directly just means you're invoking a method from whatever thread is currently executing, and the run() method goes onto the current call stack rather than at the beginning of a new call stack.

The following code does not start a new thread of execution: Thread t = new Thread(); t.run(); // Legal, but does not start a new thread

Think of the join() method as saying, "Hey thread, I want to join on to the end of you. Let me know when you're done, so I can enter the runnable state." The wait() method lets a thread say, "there's nothing for me to do now, so put me in your waiting pool and notify me when something happens that I care about."

The notify() method is used to send a signal to one and only one of the threads that are waiting in that same object's waiting pool. All three methods—wait(), notify(), and notifyAll()—must be called from within a synchronized context!

Instantiating a Thread class MyThread extends Thread { public void run() { System.out.println("Important job running in MyThread"); } public void run(String s) { System.out.println("String in run is " + s); } }

The overloaded run(String s) method will be ignored by the Thread class unless you call it yourself. If you extended the Thread class, instantiation is dead simple (we'll look at some additional overloaded constructors in a moment): MyThread t = new MyThread()

The join() Method Thread t = new Thread(); t.start(); t.join();

The preceding code takes the currently running thread (if this were in the main() method, then that would be the main thread) and joins it to the end of the thread referenced by t. In other words, the code t.join() means "Join me (the current thread) to the end of t, so that t must finish before I (the current thread) can run again."

Let's take a look at this in some code. In this example, there is one class that performs a calculation and many readers that are waiting to receive the completed calculation. At any given moment many readers may be waiting. 1. class Reader extends Thread { 2. Calculator c; 3. 4. public Reader(Calculator calc) { 5. c = calc; 6. } 7. 8. public void run() { 9. synchronized(c) { 10. try { 11. System.out.println("Waiting for calculation..."); 12. c.wait(); 13. } catch (InterruptedException e) {} 14. System.out.println("Total is: " + c.total); 15. } 16. } 17. 18. public static void main(String [] args) { 19. Calculator calculator = new Calculator(); 20. new Reader(calculator).start(); 21. new Reader(calculator).start(); 22. new Reader(calculator).start(); 23. calculator.start(); 24. } 25. } 26. 27. class Calculator extends Thread { 28. int total; 29. 30. public void run() { 31. synchronized(this) { 32. for(int i=0;i<100;i++) { 33. total += i; 34. } 35. notifyAll(); 36. } 37. } 38. }

The program starts three threads that are all waiting to receive the finished calculation (lines 18-24), and then starts the calculator with its calculation. Note that if the run() method at line 30 used notify() instead of notifyAll(), only one reader would be notified instead of all the readers.

The yield() Method - What yield() is supposed to do is make the currently running thread head back to runnable to allow other threads of the same priority to get their turn. So the intention is to use yield() to promote graceful turn-taking among equal-priority threads.

There's no guarantee the yielding thread won't just be chosen again over all the others! So while yield() might—and often does—make a running thread give up its slot to another runnable thread of the same priority, there's no guarantee.

Using notifyAll( ) When Many Threads May Be Waiting

This is especially important if you have several threads waiting on one object, but for different reasons, and you want to be sure that the right thread (along with all of the others) gets notified. notifyAll(); // Will notify all waiting threads All of the threads will be notified and start competing to get the lock. As the lock is used and released by each thread, all of them will get into action without a need for further notification.

What Happens If a Thread Can't Get the Lock? If a thread tries to enter a synchronized method and the lock is already taken, the thread is said to be blocked on the object's lock. Essentially, the thread goes into a kind of pool for that particular object and has to sit there until the lock is released and the thread can again become runnable/running. Just because a lock is released doesn't mean any particular thread will get it. There might be three threads waiting for a single lock, for example, and there's no guarantee that the thread that has waited the longest will get the lock first.

When thinking about blocking, it's important to pay attention to which objects are being used for locking. ■ Threads calling non-static synchronized methods in the same class will only block each other if they're invoked using the same instance. That's because they each lock on this instance, and if they're called using two different instances, they get two locks, which do not interfere with each other. ■ Threads calling static synchronized methods in the same class will always block each other—they all lock on the same Class instance. ■ A static synchronized method and a non-static synchronized method will not block each other, ever. The static method locks on a Class instance while the non-static method locks on the this instance—these actions do not interfere with each other at all. Same for synchronized blocks as well

Implementing java.lang.Runnable

class MyRunnable implements Runnable { public void run() { System.out.println("Important job running in MyRunnable");} }

How to print which thread is being executed

class NameRunnable implements Runnable { public void run() { System.out.println("NameRunnable running"); System.out.println("Run by " + Thread.currentThread().getName()); } } public class NameThread { public static void main (String [] args) { NameRunnable nr = new NameRunnable(); Thread t = new Thread(nr); t.setName("Fred"); t.start(); } } Running this code produces the following, extra special, output: % java NameThread NameRunnable running Run by Fred

Starting & Running multiple threads - class NameRunnable implements Runnable { public void run() { for (int x = 1; x <= 3; x++) { System.out.println("Run by " + Thread.currentThread().getName() + ", x is " + x); } } } public class ManyNames { public static void main(String [] args) { // Make one Runnable NameRunnable nr = new NameRunnable(); Thread one = new Thread(nr); Thread two = new Thread(nr); Thread three = new Thread(nr); one.setName("Fred"); two.setName("Lucy"); three.setName("Ricky"); one.start(); two.start(); three.start(); } }

code might produce the following: % java ManyNames Run by Fred, x is 1 Run by Fred, x is 2 Run by Fred, x is 3 Run by Lucy, x is 1 Run by Lucy, x is 2 Run by Lucy, x is 3 Run by Ricky, x is 1 Run by Ricky, x is 2 Run by Ricky, x is 3 -----------Do remember ----------- "The behavior is not guaranteed." AND -- Each thread will start, and each thread will run to completion.

Starting a Thread t.start();

efining, instantiating, and starting a thread: class FooRunnable implements Runnable { public void run() { for(int x = 1; x < 6; x++) { System.out.println("Runnable running"); } } } public class TestThreads { public static void main (String [] args) { FooRunnable r = new FooRunnable(); Thread t = new Thread(r); t.start(); } }

What will be the output of the following - public class NameThreadTwo { public static void main (String [] args) { System.out.println("thread is " + Thread.currentThread().getName()); } }

prints out % java NameThreadTwo thread is main

Making a Thread - for the purpose of exam you need to know the minimum foll methods

start() yield() sleep() run()

Three ways a thread could leave a runnable state ■ A call to sleep() ■ A call to yield() ■ A call to join()

■ A call to sleep() Guaranteed to cause the current thread to stop executing for at least the specified sleep duration (although it might be interrupted before its specified time). ■ A call to yield() Not guaranteed to do much of anything, although typically it will cause the currently running thread to move back to runnable so that a thread of the same priority can have a chance. ■ A call to join() Guaranteed to cause the current thread to stop executing until the thread it joins with completes, or if the thread it's trying to join with is not alive, however, the current thread won't need to back out

Two ways you can define & instatiate a thread

■ Extend the java.lang.Thread class. ■ Implement the Runnable interface.

Synchronization & Locks - Only methods (or blocks) can be synchronized, not variables or classes. ■ Each object has just one lock. ■ Not all methods in a class need to be synchronized. A class can have both synchronized and non-synchronized methods.

■ If two threads are about to execute a synchronized method in a class, and both threads are using the same instance of the class to invoke the method, only one thread at a time will be able to execute the method.

The constructors that Thread class takes- all important for exam

■ Thread() ■ Thread(Runnable target) ■ Thread(Runnable target, String name) ■ Thread(String name)


Ensembles d'études connexes

Triangle Shirtwaist Factory Fire Study

View Set

Sociology Chapter 9- Race and Ethnicity

View Set

Strayer Chapter 1: Before 1200 ~ Patterns in World History

View Set

Lewis Ch 50 Nursing Management: Endocrine Problems NCLEX

View Set

Creative Writing Midterm Exam Review 18-19

View Set

MLT 107: Ch.1 Bacterial Cell structure, physiology, metabolism, and genetics

View Set