290 likes | 375 Views
Multithreading (cont.). Steps to Programming/Running a Threads. Implement a class that extends the Thread class Place the code for your task into the run method of your class Create an object of your subclass Call the start method of your class to start the thread
E N D
Multithreading (cont.)
Steps to Programming/Running a Threads • Implement a class that extends the Thread class • Place the code for your task into the run method of your class • Create an object of your subclass • Call the start method of your class to start the thread • When a Thread object is started, the code in its run method is executed in a new thread
GreetingThread Outline • A program to print a time stamp and "Hello World" once a second for ten seconds public class GreetingThread extends Thread { public void run() { //thread action . . . } //variables used by the thread action . . . }
Thread Action for GreetingThread • Print a time stamp • Print the greeting • Wait a second
GreetingThread • We can get the date and time by constructing Date object Date now = new Date(); • To wait a second, use the sleep method of the Thread class sleep(milliseconds) • A sleeping thread can generate an InterruptedException • Catch the exception • Terminate the thread
GreetingThreadrunmethod public void run() { try { //thread action } catch (InterruptedException e) { //cleanup, if necessary } }
File GreetingThread.java import java.util.Date; /** A thread that repeatedly prints a greeting. */ public class GreetingThread extends Thread { /** Constructs the thread object. @param aGreeting the greeting to display */ public GreetingThread(String aGreeting) { greeting = aGreeting; }
public void run( ) { try { for (int i = 1; i <= REPETITIONS; i++) { Date now = new Date(); System.out.println(now + " " + greeting); sleep(DELAY); } } catch (InterruptedException exception) { } } private String greeting; private static final int REPETITIONS = 10; private static final int DELAY = 1000; } /* end class */
To Start the Thread • Construct an object of your thread classGreetingThread t = new GreetingThread("Hello World"); • Call the start methodt.start();
File GreetingThreadTest.java import java.util.Date; /** This program tests the greeting thread by running two threads in parallel. */ public class GreetingThreadTest { public static void main(String[] args) { GreetingThread t1 = new GreetingThread("Hello, World!"); GreetingThread t2 = new GreetingThread("Goodbye, World!"); t1.start(); t2.start(); } }
Thread Scheduler • The thread scheduler runs each thread for a short amount of time called a time slice (quantum) • Then the scheduler picks another thread from those that are runnable • A thread is runnable if it is not asleep or blocked in some way • There is no guarantee about the order in which threads are executed
Terminating Threads • A thread terminates when its run method returns • Do not terminate a thread using the deprecated stop method • Instead, notify a thread that it should terminate t.interrupt();
Terminating Threads • A thread's run method should check occasionally whether it has been interrupted • Use the isInterrupted method • An interrupted thread should release resources, clean up, and exit • The sleep method throws an InterruptedException when a sleeping thread is interrupted • Catch the exception • Terminate the thread
Terminating a Thread public void run( ) { try { for (int = 1; i <= REPETITIONS &&!isInterrupted(); i++) { //do the work } } catch (InterruptedException exception) { //handling the exception } //cleanup }
Corrupting Data with Unsynchronized Threads • When threads share a common object, they can conflict with each other. • In this example, a DepositThread and a WithdrawThread both manipulate a single BankAccount
Sample Application • Create a BankAccount object • Create a DepositThread t0 to deposit $100 into the account for 10 iterations • Create a WithdrawThread t1 to withdraw $100 from the account for 10 iterations • The result should be zero, but sometimes it is not
Scenario to Explain Non-zero Result • The first thread t0 executes the lines System.out.print("Depositing " + amount); double newBalance = balance + amount; • t0 reaches the end of its time slice and t1 gains control • t1 calls the withdraw method which withdraws $100 from the balance variable. • Balance is now -100 • t1 goes to sleep
Scenario to Explain Non-zero Result (cont.) • t0 regains control and picks up where it left off. • t0 executes the lines System.out.println(", new balance is " + newBalance); balance = newBalance; • The balance is now 100 instead of 0 because the deposit method used the OLD balance • This is called a race condition.
Race condition • Occurs if the effect of multiple threads on shared data depends on the order in which the threads are scheduled • It is possible for a thread to reach the end of its time slice in the middle of a statement. • It may evaluate the right-hand side of an assignment but not be able to store the result until its next turn.
File BankAccountThreadTest.java /** This program runs two threads that deposit and withdraw money from the same bank account. */ public class BankAccountThreadTest { public static void main(String[] args) { BankAccount account = new BankAccount(); DepositThread t0 = new DepositThread(account, 100); WithdrawThread t1 = new WithdrawThread(account, 100); t0.start(); t1.start(); } }
File DepositThread.java /** A deposit thread makes periodic deposits to a bank account. */ class DepositThread extends Thread { /** Constructs a deposit thread. @param anAccount the account into which to deposit money @param anAmount the amount to deposit in each repetition */ public DepositThread( BankAccount anAccount, double anAmount) { account = anAccount; amount = anAmount; }
public void run() { try { for (int i = 1; i <= REPETITIONS && !isInterrupted(); i++) { account.deposit(amount); sleep(DELAY); } } catch (InterruptedException exception) { } } private BankAccount account; private double amount; private static final int REPETITIONS = 10; private static final int DELAY = 10; } /* end class */
run Method of DepositThread public void run() { try { for (int i = 1; i <= REPETITIONS && !isInterrupted(); i++) { account.deposit(amount); sleep(DELAY); } } catch (InterruptedException exception) { } }
File WithdrawThread.java /** A withdraw thread makes periodic withdrawals from a bank account. */ class WithdrawThread extends Thread { /** Constructs a withdraw thread. @param anAccount the account from which to withdraw money @param anAmount the amount to withdraw in each repetition */ public WithdrawThread(BankAccount anAccount, double anAmount) { account = anAccount; amount = anAmount; }
public void run() { try { for (int i = 1; i <= REPETITIONS && !isInterrupted(); i++) { account.withdraw(amount); sleep(DELAY); } } catch (InterruptedException exception) { } } private BankAccount account; private double amount; private static final int REPETITIONS = 10; private static final int DELAY = 10; }
File BankAccount.java /** A bank account has a balance that can be changed by deposits and withdrawals. */ public class BankAccount { /** Constructs a bank account with a zero balance */ public BankAccount() { balance = 0; } /** Deposits money into the bank account. @param amount the amount to deposit */
public void deposit(double amount) { System.out.print("Depositing " + amount); double newBalance = balance + amount; System.out.println(", new balance is " + newBalance); balance = newBalance; } /** Withdraws money from the bank account. @param amount the amount to withdraw */ public void withdraw(double amount) { System.out.print("Withdrawing " + amount); double newBalance = balance - amount; System.out.println(", new balance is " + newBalance); balance = newBalance; }
/** Gets the current balance of the bank account. @return the current balance */ public double getBalance() { return balance; } private double balance; }
Sometimes ... The final balance is not zero! The data is corrupted!