Скачать презентацию
Идет загрузка презентации. Пожалуйста, подождите
Презентация была опубликована 8 лет назад пользователемНина Щербина
1 1 © Luxoft Training 2013 Multithreading in Java
2 2 © Luxoft Training 2013 What does it mean to have more than one call stack?
3 3 © Luxoft Training 2013 Multithreading Multithreading – a way to work with a single JVM as with several JVMs Multithreading allows multiple threads to exist within the context of a single process These threads share the process's resources, but are able to execute independently.
4 4 © Luxoft Training 2013 How to launch a new thread? Make a Runnable object (the threads job) Runnable threadJob = new MyRunnable(); Make a Thread object (the worker) and give it a Runnable (the job) Thread myThread = new Thread(threadJob); Start the Thread myThread.start();
5 5 © Luxoft Training 2013
6 6 Interface Runnable public void run(); Class Thread public Thread(); public Thread(String threadName); public Thread(Runnable target); public Thread(Runnable target, String threadName); public Thread(); public Thread(String threadName); public Thread(Runnable target); public Thread(Runnable target, String threadName); 3-6 Thread and Runnable
7 7 © Luxoft Training 2013 Thread and Runnable
8 8 © Luxoft Training 2013 Created Started Runnable public void run() { … return; } Dead Running t.start() Thread t = new Thread() Thread lifecycle
9 9 © Luxoft Training 2013 Example: ThreadTutor Thread lifecycle
10 10 © Luxoft Training 2013 Thread Newly Created Start Thread Runnable Running Dead Blocked Programmer Scheduler Thread states
11 11 © Luxoft Training 2013 The Thread.sleep() method is a static method of a thread: public static void sleep(long milliseconds) throws InterruptedException public static void sleep(long milliseconds, int nanoseconds) throws InterruptedException Thread.sleep() method
12 12 © Luxoft Training 2013 Using sleep() method public class SleepMessages { public static void main(String args[]) throws InterruptedException { String importantInfo[] = { "Mares eat oats", "Does eat oats", "Little lambs eat ivy", "A kid will eat ivy too" }; for (int i = 0; i < importantInfo.length; i++) { //Pause for 4 seconds Thread.sleep(4000); //Print a message System.out.println(importantInfo[i]); }
13 13 © Luxoft Training 2013 Thread.interrupt() Any Thread can be interrupted by calling interrupt() method. If the thread was blocked by invoking the sleep() or wait() methods, then when the interrupt() method is called for the current thread and the execution of the blocked method (e.g., sleep() ) will be interrupted and the method will throw InterruptedException. Usually we have to put sleep to the try-catch block: try { Thread.sleep(100); } catch (InterruptedException e) { // sleeping was interrupted e.printStackTrace(); }
14 14 © Luxoft Training 2013 Thread states diagram
15 15 © Luxoft Training 2013 Thread priorities int oldPriority = theThread.getPriority(); int newPriority = Math.min(oldPriority+1, Thread.MAX_PRIORITY); theThread.setPriority(newPriority);
16 16 © Luxoft Training 2013 Example: ThreadTutor2 Thread priorities
17 17 © Luxoft Training 2013 Lost update problem class TestSync implements Runnable { private int balance; public void run() { for (int i = 0; i < 50; i++) { increment(); System.out.println( balance is + balance); } public void increment() { int i = balance; balance = i + 1; } public class TestSyncTest { public static void main (String[] args) { TestSync job = new TestSync(); Thread a = a.start(); Thread b = b.start(); }
18 18 © Luxoft Training 2013 Solving lost update problem public synchronized void increment() { int i = balance; balance = i + 1; } Two steps in one unbreakable unit Once a thread enters the method, we have to make sure that all the steps in the method complete (as one atomic process) before any other thread can enter the method. public void increment() { synchronized(this) { int i = balance; balance = i + 1; } lock monitor
19 19 © Luxoft Training 2013 Should we put all code to synchronize blocks? - Synchronized method has a certain amount of overhead - Synchronized method can slow your program down -Synchronized method forces other threads to get in line and wait their turn - Synchronized method can lead to the deadlock public void go() { doStuff(); synchronized(this) { criticalStuff(); moreCriticalStuff(); } Synchronize only the bare minimum that should be synchronized!
20 20 © Luxoft Training 2013 Mailbox example public class MailReader extends Thread { private Mailbox myMailbox; public MailReader(Mailbox box) { this.myMailbox = box; } public void run() { while (true) { if (myMailbox.request) { System.out.println(myMailbox.message); myMailbox.request = false; } try { sleep(50); } catch (InterruptedException e) { } class Mailbox { public boolean request; public String message; } One thread stores a message to Mailbox object, another thread retrieves it: The MailReader class has two serious problems: Data corruption is possible as clients thread concurrently modifies the message and the request flag. Its difficult to choose a time for sleeping.
21 21 © Luxoft Training 2013 How the object lock is working? It can be expressed metaphorically: There are several phone kiosks; all of them have identical locks. Several people want to make calls from one kiosk. Entering the kiosk requires opening the lock. There is only one lock. Lock is necessary only for shared objects
22 22 © Luxoft Training 2013 How the object lock is working?
23 23 © Luxoft Training 2013 Mailbox with synchronization class Mailbox { private boolean request; private String message; public synchronized void storeMessage(String message) { request = true; this.message = message; } public synchronized String retrieveMessage() { request = false; return message; } Now, when the mailbox.retrieveMessage() is called, the MailReader thread will be prevented from corrupting the mailbox object. Choosing the time for checking for new messages is still problematic.
24 24 © Luxoft Training 2013 Entering into synchronized blocks
25 25 © Luxoft Training 2013 Synchronization options To synchronize an entire method, using the lock of the object that owns the method: public synchronized String retrieveMessage() {…} In this case this is a monitor. It can be used if the methods of the same object have to be run successively. To synchronize part of a method, using the lock of an arbitrary object: synchronized(monitor) To synchronize part of a method, using the lock of the object that owns the method: synchronized(this)
26 26 © Luxoft Training 2013 Example: SynchronizedTutor Controlling Threads
27 27 © Luxoft Training 2013 Example: SynchronizedTutor1 Controlling Threads
28 28 © Luxoft Training 2013 Some threads may be marked as daemon threads. Daemon threads are infrastructure threads, created automatically by the JVM (e.g., garbage collector) Before a thread begins execution, you can change its daemon status by calling its setDaemon() method. The JVM runs until the only live threads are daemons. Mark thread as the daemon if thats background auxiliary process. JVM only waits for the normal processes to finish, not for the daemon! Daemon Threads
29 29 © Luxoft Training 2013 Example: DaemonTest Daemon threads
30 30 © Luxoft Training 2013 The wait() & notify() methods provide a way for a shared object to pause a thread when it becomes unavailable to that thread and to allow the thread to continue when appropriate. Now I notify() that phone is free again. My line is busy. I have nothing to do now. I can sleep and check if the phone is available again. I will wait(), and others can use phone kiosk. Please notify me when I should call again. Until that I an BLOCKED. Scheduler: the next, please! The shared monitor wait() and notify()
31 31 © Luxoft Training 2013 wait() and notify() The wait() & notify() methods are defined in Object class and must be called in synchronized block: // monitor - any SHARED object // of waiting and notifier threads Object monitor = new Object(); boolean waitingThreadCanTryAgain = false; // waiting thread code: synchronized(monitor) { while (!waitingThreadCanTryAgain) { monitor.wait(); } // notifier thread code: synchronized(monitor) { // make a phone call or smth. else waitingThreadCanTryAgain = true; monitor.notify(); }
32 32 © Luxoft Training 2013 wait() and notify()
33 33 © Luxoft Training 2013 Producer-consumer pattern Message consumer: Im waiting for the message from other thread. I have nothing to do now. I can sleep and check if the message has come. But I will wait() instead. Please notify() me when I message should be checked. Until that I an BLOCKED. Message producer: Now the message Is ready. I notify() the thread to read it. Monitor object theMessage This is a typical use case for all tasks when 2 threads need to communicate.
34 34 © Luxoft Training 2013 Consumer thread ceases the execution if message has not been retrieved: public synchronized String retrieveMessage() { // keep waiting if nothing is produced to consume while (request == false) { try { wait(); // give up lock and wait } catch (InterruptedException e) { // keep trying } request = false; // consume return message; } Producer-consumer pattern public synchronized void storeMessage(String message) { this.message = message; // produce request = true; notify(); // notify waiting threads to resume }
35 35 © Luxoft Training 2013 public class ConsumerProducer { private int count; public synchronized void consume() { // keep waiting if nothing is produced to consume while (count == 0) { try { wait(); // give up lock and wait } catch (InterruptedException e) { // keep trying } count--; // consume } public synchronized void produce() { count++; // produce notifyAll(); // notify waiting threads to resume } Producer-consumer pattern
36 36 © Luxoft Training 2013 Lifecycle of the thread
37 37 © Luxoft Training 2013 wait() and notify() The statement used to check whether the thread must wait should be put into while {} If the waiting thread receives an interrupt() call it will cease wait() of the thread and moves in Seeking Lock state. Usually, after that you need to check the waiting condition once again. wait() To restore a waiting thread when the monitor state changes call the notify() method. The notify() method arbitrarily selects one of the threads in the monitors waiting pool and moves it to the Seeking Lock state. notify()
38 38 © Luxoft Training 2013 notifyAll() In real life there is usually little sense in moving only one arbitrary thread from waiting pool to Seeking lock state That is why the notifyAll() method moving all threads from waiting pool to Seeking lock state is preferred. Now I notifyAll() that phone is free again. We are all awakened, but only one of us will occupy the phone kiosk.
39 39 © Luxoft Training 2013 wait(xxx) Also the Object class defines the wait(xxx) method, where xxx is a number of milliseconds If the waiting thread hasnt moved to Seeking lock state by called notify(), then when the xxx elapses it will move to this state automatically My line is busy. I will wait(500), for 500 milliseconds, and after that I will get alive and will do something else. I am BLOCKED for 5 sec.
40 40 © Luxoft Training 2013 wait() and sleep() compared
41 41 © Luxoft Training 2013 Example: WaitTutor Controlling Threads 3-41
42 42 © Luxoft Training 2013 Example: WaitTutor1: solution for WaitTutor Controlling Threads 3-42
43 43 © Luxoft Training 2013 Pipes and multithreading Example: PipedTutor
44 44 © Luxoft Training 2013 The Thread.stop() method The Thread.stop() method forcibly terminates the thread regardless of its state. The method is deprecated, as it can corrupt the data. Actually, client code is not aware of the code that executes the thread and may call Thread.stop() at the most inappropriate moment, in the middle of the operation, which will corrupt the data 3-44
45 45 © Luxoft Training 2013 A gentle way to terminate the thread // this is a shared flag visible for both threads boolean shouldTerminate = false; // we want to interrupt the thread shouldTerminate = true; // inside the run method of the thread to be terminated: if (shouldTerminate) return; public void run() { while(true) { // do some job if (shouldTerminate) return; }
46 46 © Luxoft Training 2013 Not so gentle way to terminate the thread // this is a shared data visible for both threads TestThread t = new TestThread(); Object monitor = new Object(); boolean shouldTerminate = false; // we want to interrupt the thread in another thread: shouldTerminate = true; t.interrupt(); class TestThread extends Thread { public void run() { while(true) { synchronized(monitor) { try { monitor.wait(); } catch (InterruptedException e) { if (shouldTerminate) return; } if (shouldTerminate) return; }
47 47 © Luxoft Training 2013 Example: WaitTerminateTutor Terminating the thread 3-47
48 48 © Luxoft Training 2013 Example: WaitTerminateTutor solution: WaitTerminateTutor1 Terminating the thread 3-48
49 49 © Luxoft Training 2013 Terminating the thread 3-49 Example: WaitTerminateTutor solution: WaitTerminateTutor2
50 50 © Luxoft Training 2013 Deadlock Deadlock is when a thread blocks because it is waiting for a condition, and something else in the program makes it impossible for that condition to arise Can arise for many reasons. Classic example is deadly embrace:
51 51 © Luxoft Training 2013 Deadly embrace. Example 3-51 public class Deadlock implements Runnable { public void run() { while (true) { synchronized (firstResource) { synchronized (secondResource) { // simulate some time consuming activity try { Thread.sleep(100); } catch (InterruptedException ex) { }
52 52 © Luxoft Training Deadly embrace. Example (cont.) public static void main(String[] args) { Object a = "Resource A"; Object b = "Resource B"; Thread t1 = new Thread(new Deadlock(a, b)); Thread t2 = new Thread(new Deadlock(b, a)); t1.start(); t2.start(); } private Object firstResource; private Object secondResource; public Deadlock(Object first, Object second) { firstResource = first; secondResource = second; }
53 53 © Luxoft Training 2013 Example: DeadlockTutor Deadly embrace 3-53
Еще похожие презентации в нашем архиве:
© 2024 MyShared Inc.
All rights reserved.