1 / 79

COMP201 Java Programming Part III: Advanced Features

COMP201 Java Programming Part III: Advanced Features. Topic 12: Multithreading Volume II,Chapter 1. Outline. Introduction : Why and what Basics: creating and running threads Issues Thread states Thread scheduling Synchronization Suspending and stopping threads Uses Animation

tate
Télécharger la présentation

COMP201 Java Programming Part III: Advanced Features

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. COMP201 Java Programming Part III: Advanced Features Topic 12: Multithreading Volume II,Chapter 1

  2. Outline • Introduction: Why and what • Basics: creating and running threads • Issues • Thread states • Thread scheduling • Synchronization • Suspending and stopping threads • Uses • Animation • Threads and Swing

  3. Introduction • Consider the program Bounce.java • Desired effects • If the Start button is clicked, a ball starts to bounce. • If the button is clicked again, a second ball starts to bounce and so on. • If the Close button is clicked, the windows closes and the program terminates • Classes • Ball • BallCanvas extends JPanel • BounceFrame • Bounce

  4. Introduction • Classes • Ball • public void draw(Graphics2D g2) • Draws the ball at its current position • public void move() • Moves the ball to the next position, reversing direction if it hits one of the edges • Request paint afterwards to update UI • class BallCanvas extends JPanel • Keeps a list of balls • public void add(Ball b) • Add a ball to the canvas. • public void paintComponent(Graphics g) • Draw all balls at their current positions

  5. Introduction • Classes • class BounceFrame extends JFrame • Set up GUI and listeners • When the Close button is clicked this method is called, public void actionPerformed(ActionEvent evt) { System.exit(0); } • When the Start Button is clicked, this method is called public void actionPerformed(ActionEvent evt) { addBall(); // Creates and adds a bouncing ball to the canvas // and make it bounce 1,000 times. }

  6. Introduction public void addBall() { try { Ball b = new Ball(canvas); // create a ball canvas.add(b); // add it to the canvas // bounce it 1,000 times for (int i = 1; i <= 1000; i++) { b.move(); Thread.sleep(5); // sleep for 5 milliseconds }} catch (InterruptedException exception){} } Note: sleep is a static method that puts the currently running thread to sleep. It throws InterruptedException when interrupted.

  7. Introduction • However • Cannot start a second ball before the current ball finishes bouncing • Cannot terminate program before the current ball finishes bouncing • Actually, won’t even work if repaint is used (as it should be) instead of paint (see end of Bounce.java)!!!!!

  8. Introduction • Why? • There is a single thread of control. • Actions are executed one by one. • Cannot execute next action before current action finishes • Implications in general: • Cannot do anything else while waiting data from the net. • Cannot stop downloading even though you know, after seeing part of the download, that you don’t want the download any more • Solution: Multithreading

  9. Introduction • A multithreaded program has multiple threads of control • OS runs one thread a short period of time, then switches to another, and so on • To user, threads appear to run simultaneously. An illusion. • Nonetheless, makes it easier for user to interact with program

  10. Introduction • In our example, we need more than one thread: • One thread to listen for button clicks • One thread to bounce each ball //BounceThread.java

  11. Outline • Introduction: Why and what • Basics: creating and running threads • Issues • Thread states • Thread scheduling • Synchronization • Suspending and stopping threads • Uses • Animation • Threads and Swing

  12. Creating and Running Threads • How to create and run new threads (from the current thread)? • Write a class for thread • Either a class that extends the class java.lang.Thread class MyThreadClass extends Thread {…} • Or a class that implements the interface java.lang.Runnable class MyRunnableClass implements Runnable { ….} • Specify what the new thread should do in the method void run() class MyThreadClass extends Thread { public void run() {// codes for new thread to run } …}

  13. Creating and Running Threads • How to create and run new threads? • Create an object of the thread class MyThreadClass t = new MyThreadClass(); Thread t = new Thread( new MyRunnableClass() ); • Start a new thread by calling the start method t.start() • Notes: • Don’t call run directly. “run” does not create new thread • “start” does thread setup and calls “run”

  14. Creating and Running Threads • In our example, we want a separate thread to bounce each ball. So we first define this thread class class BallThread extends Thread { public BallThread(Ball aBall) { b = aBall; } public void run() // codes for new thread { try { for (int i = 1; i <= 1000; i++) { b.move(); sleep(5); }} catch (InterruptedException exception { } } private Ball b; }

  15. Creating and Running Threads • Next, we modify the addBall method of BounceFrame to • add a bouncing ball to the canvas and • start a thread to make it bounce public void addBall() { Ball b = new Ball(canvas); canvas.add(b); BallThread thread = new BallThread(b); thread.start(); } // BounceThread.java // try to replace start with run and see what happens

  16. Creating and Running Threads • Event dispatch thread • Why? • In BounceThread.java, the move method calls repaint() • In Bounce.java, the move method calls paint(canvas.getGraphics()); • Any program starts in the main thread, when the main method is called • In a GUI program, the main thread creates a window and a event dispatch thread to handle events. It usually dies thereafter. • repaint() generates an PaintEvent, which is handled by the event dispatch thread. • In Bounce.java, the event dispatch thread is consumed by the addBall operation for 5 seconds • During that time, it cannot handle any events. It does not handle paint event. • So, the ball would not be painted if repaint() was used instead of paint.

  17. Creating and Running Threads • RunnableTest.java class RadioButtonDemo extends JPanel implements Runnable { … public void run () { // display images one by one } public void showPicture() { if (runner == null) { runner = new Thread(this); // create thread runner.start(); // run thread }} private Thread runner; …}

  18. Creating and Running Threads Invoke the showPicture method showButton.addActionListener( new ActionListener() { public void actionPerformed( ActionEvent e) { showNow = true; showPicture(); } } );

  19. Outline • Introduction: Why and what • Basics: creating and running threads • Issues • Thread states • Thread scheduling • Synchronization • Suspending and stopping threads • Uses • Animation • Threads and Swing

  20. Thread States Four states for threads: new, runnable, blocked, dead sleep blocked done sleeping new suspend resume start wait runnable notify Wait for lock Lock available block on I/O runexits stop dead I/O complete Note: suspend, resume,stop deprecated.

  21. new start runnable Thread States • When a thread has just been created using the newoperator, it is in the newstate. • Once start method is invoked (which calls the run method), the thread becomes runnable. • A runnable thread might not be running. • There can be many runnable threads. But only one of them can be running at any time point. • OS decides which thread to run. More on this later.

  22. Thread States • A runnable thread enters the blocked state when • The thread is currently running and methodThread.sleepis called • suspend method of the thread is called. (deprecated) • The thread calls thewaitmethod. • The thread tries to lock an object locked by another thread. • The thread calls an operation that is blocked on i/o. sleep blocked suspend wait runnable A blocked thread cannot be running Wait for lock block on I/O

  23. Thread States • A blocked reenters runnable state when • It has slept the specified amount of time. • resume method of the thread is called. (deprecated) • Another method calls notifyornotifyAll • Object lock released by other thread • I/O completed. blocked done sleeping resume runnable notify Lock available I/O complete

  24. Thread States • A runnable thread enters the dead state when • Its run method exits. Natural death. • stop method of the thread is called. (deprecated) • An exception is thrown but not caught. runnable runexits stop dead

  25. Thread States • Finding out states of threads • Method isAlive allows you to find out whether a thread is alive of dead. • This method returns true if the thread is runnable or blocked, • false if the thread is still new and not yet runnable or if the thread is dead • No way to find out whether an alive thread is running, runnable, or blocked.

  26. Outline • Introduction: Why and what • Basics: creating and running threads • Issues • Thread states • Thread scheduling • Synchronization • Suspending and stopping threads • Uses • Animation • Threads and Swing

  27. Thread Scheduling • At any time, there might be many runnable threads. But only one of them is actually running. • The thread scheduler decides which runnable thread to run. • Questions: • When does the thread scheduler kick in and pick a thread to run? • How does the thread scheduler select among the runnable threads? • A not-so-precise answer: • A running Java thread will continue to run until • It calls yield method, or • It ceases to be runnable (dead or blocked), or • Another thread with higher priority moves out of blocked state • Then the thread scheduler kicks in and picks another thread with the highest priority to run

  28. Thread Scheduling • Two different thread implementations • “Native thread” implementation (e.g. Windows): Performs time-slicing. Interrupts the running thread periodically to give other threads a chance to run. • “Green thread” implementation (e.g. Solaris) Does not perform time-slicing. It keeps a running thread active until a higher-priority thread awakes and takes control.

  29. Thread Scheduling • The answer on slide 17 is precise for the green thread implementation. • For the native thread implementation, the precise answer is • A running Java thread will continue to run until • It calls yield method, or • It ceases to be runnable (dead or blocked), or • Another thread with higher priority moves out of blocked state, or • It is pre-emptied by OS (time-slicing). • Then the thread scheduler kicks in and picks another thread with the highest priority to run

  30. Thread Scheduling • Priority of individual threads • Can be increased or decreased using setPriority • Java have 10 priority levels (constants of Thread class) MIN_PRIORITY = 1; NORMAL_PRIORITY = 5; MAX_PRIORITY = 10 • A thread inherits priority from its parent thread, the one the creates it. • Note • Some OS has fewer. E.g. Windows NT has 7. • JVM maps Java priority levels to priority level of the underlying OS.

  31. Thread Scheduling • Example: BounceExpress.java • Two kinds of balls: black and red. • Red ball threads have higher priority and hence get more chance to run. The effect is that red balls appear to be faster.

  32. Thread Scheduling • The addBall method public void addBall(int priority, Color color) { Ball b = new Ball(canvas, color); canvas.add(b); BallThread thread = new BallThread(b); thread.setPriority(priority); thread.start(); }

  33. Thread Scheduling • Buttons and listeners addButton(buttonPanel, "Start", new ActionListener() { public void actionPerformed(ActionEvent evt) { addBall(Thread.NORM_PRIORITY, Color.black); }}); addButton(buttonPanel, "Express", new ActionListener() { public void actionPerformed(ActionEvent evt) { addBall(Thread.NORM_PRIORITY + 2, Color.red); } });

  34. Thread Scheduling • Question 1: • Consider the case when there are 1 black ball and 1 red ball. • When the red-ball thread goes to sleep, there is only one other thread, the black-ball thread. • Hence the black-ball thread must be chosen. • Implication: • black ball takes one move, red ball takes one move, black ball takes one move, and so on. • The two balls should be of the same speed. • Well, this is not the case. Why? • There is another thread! What is it? What role does it play? • When event dispatch thread pauses, the red-ball thread already wake up from sleep and hence picked by scheduler over back-ball thread. • (Is pre-emption a reason?)

  35. Thread Scheduling • Question 2: • If we change sleeping to 50, red balls are not faster any more. • Why? • In order for the red-ball thread to be picked more often than the black-ball thread, it must “meet” the scheduler more often. • When event dispatch thread pauses, the red-ball thread is still sleeping, just as the black-ball thread.

  36. sleepvs. yield • In BallThread, sleep is called to give other thread a chance to run. • Another way is to call yield. class BallThread extends Thread { public BallThread(Ball aBall) { b = aBall; } public void run() // codes for new thread { for (int i = 1; i <= 1000; i++) { b.move(); yield(); // used to be sleep(5) } } private Ball b; }

  37. sleepvs. yield • There is a big difference • Calling sleep put the current running thread into the blocked state • Calling yield does not put the calling thread, t1, into the blocked state • It merely let the scheduler kick in and pick another method to run. • It might happen that the t1 is select to run again. This happens when t1 has a higher priority than all other runnable threads. BounceExpress1/BounceExpress.java

  38. Thread Scheduling • Cooperating vs. Selfish threads: • A cooperating thread gives others a chance to run • Calling sleep: pause for the specified period of time • Calling yield: pause temporarily. Scheduler kicks in. • A selfish thread does none of this. • Effects of selfish threads are system-dependent: • Green thread: A selfish thread can consume all the CPU time. • Native thread: A selfish thread doesn’t post a big problem.

  39. Thread Scheduling • BounceSelfish.java public void run() { try { for (int i = 1; i <= 1000; i++) { b.move(); if (selfish) { // busy wait for 5 milliseconds long t = System.currentTimeMillis(); while (System.currentTimeMillis() < t + 5 ; } else sleep(5); }} catch (InterruptedException exception){} }

  40. Thread Scheduling • Question 3: • The balls some times jump. • Why? • Event dispatch thread does get the time to run. Paint events accumulate.

  41. Outline • Introduction: Why and what • Basics: creating and running threads • Issues • Thread states • Thread scheduling • Synchronization • Suspending and stopping threads • Uses • Animation • Threads and Swing

  42. Synchronization • The Synchronization problem: Two different threads modify the same object atthe same time, leading to corrupted object. Such a situation is called race condition. • An analog: • You and your partner are finishing a group project and starting to write the project report. • The report is kept at a centralized location. • You open the report and edit it • Your partner opens the report and edits it • You save the edits. • Your partner saves his edits, • Your edits are lost!

  43. Synchronization • An example: UnsynchBankTest.java • class Bank • A bank with a number of bank accounts. • class TransferThread extends Thread • A thread that transfers money from an account to other accounts in a bank. • public class UnsynchBankTest • Create 10 accounts and multiple threads to make random transfers

  44. Synchronization • class Bank public voidtransfer(int from, int to, int amount) { if (accounts[from] < amount) return ; accounts[from] -= amount; int tmp = accounts[to]; // added by Instructor so that corruption occurs more easily try { Thread.sleep(1); } catch(InterruptedException e) {} accounts[to] = tmp + amount; //test: print out total after every 1000 transactions ntransacts++; if (ntransacts % 1000 == 0) test(); }

  45. Synchronization • class TransferThread extends Thread class TransferThread extends Thread { public TransferThread(Bank b, int from, int max) {…} public void run() { try { while (!interrupted()) { int toAccount = (int)(bank.size() * Math.random()); int amount = (int)(maxAmount * Math.random()); bank.transfer(fromAccount, toAccount, amount); sleep(1); }} catch(InterruptedException e) {} } private Bank bank; private int fromAccount; private int maxAmount;

  46. Synchronization • ClassUnsynchBankTest public static void main(String[] args) { Bank b = new Bank(NACCOUNTS, INITIAL_BALANCE); int i; for (i = 0; i < NACCOUNTS; i++) { TransferThread t = new TransferThread(b, i, INITIAL_BALANCE); t.setPriority(Thread.NORM_PRIORITY + i % 2); t.start(); } } public static final int NACCOUNTS = 10; public static final int INITIAL_BALANCE = 10000; Note: Total amount in all accounts = 100,000

  47. Synchronization • Run the program • Very quickly, the amounts in the accounts do not add up to 100,000 • Why? • The transfer method of Bank class is not atomic: consists of many steps • Can be interrupted in the middle

  48. Synchronization • Problem scenario: • Thread 1 • Takes 50 from Account A • Reads current balance of Account B and stores value in variable tmp • Goes to sleep (simulate interruption, self interruption) • Thread 2 • Deposit some fund to Account B • Thread 1 • Update balance of Account B: tmp + 50 • Result: • Deposit by Thread 2 is lost! • The total amount can only be less than 100,000

  49. Synchronization • Note that even instructions are not atomic. • Consider the following accounts[to] += amount; • It is processed in three steps as follows: • Load current value of accounts[to] to a register • Add amount • Move the result back to accounts[to].

  50. Synchronization • Execution interruption • accounts[0] is currently 100. • Thread 1 perform accounts[0] += 50; • Thread 2 performs accounts[0] += 50; • The correct result should be: accounts[0] == 200. • What is the result if the following happens? Actual result: accounts[0] == 150 The probability of such interruptions is low (but possible). This is why we faked interruption using sleep.

More Related