You are on page 1of 63

Chapter 3

1
Multitasking and Multithreading
0 Multitasking:
0 refers to a computer's ability to perform multiple jobs concurrently
0 more than one program are running concurrently, e.g., UNIX, Windows
0 Multithreading:
0 A thread is a single sequence of execution within a program
0 refers to multiple threads of control within a single program
0 each program can run multiple threads of control within it.
0 Ex: in a Web browser we may do the following tasks at the
same time:
1. scroll a page,
2. download an applet or image,
3. play sound, 4
print a page.
0 A thread is a
single sequential AP - Chapter 5 2
(Thread) 2
flow of control
Concurrency vs. Parallelism
CPU CPU1
CPU2

AP - Chapter 5 3
(Thread) 3
What Are Processes and Threads?
0 There are 3 levels of executions of computer instructions on a computer
system:
 CPU Level: There is only one flow of execution on the central
processing
unit (CPU), that is the operating system (OS).
 OS Level: For a multi-tasking OS, multiple application programs can
be managed to be executed simultaneously. Here, a flow of execution
is called a process.
 Application Level: For a well written application program, multiple
sections of codes can be managed to be executed simultaneously. Here,
a flow of execution is called a thread. A program that can manage
multiple threads is called a multi-threading program.
0 A good example of multi-threading programs are computer games that
simulate real time activities of multiple human characters and/or
moving objects.
0 Under the Java architecture, the Java virtual machine (JVM) will provide
all the help you need to create and manage multiple threads in your Java
applications.
5 4
What are Threads Good For?
0 To maintain responsiveness of an application during a long running
task
0 To enable cancellation of separable tasks
0 Some problems are naturally parallel
0 To monitor status of some resource (e.g., DB)
0 Some APIs and systems demand it (e.g., Swing)
0 Single-user programs/clients
0 continuously responsive user interfaces
0 e.g., make help menu accessible during time-consuming
database operation, etc.
0 Speed up tasks when multiple processors available
0 Servers
0 Allows multiple client connections simultaneously
AP - Chapter 5 (Thread)
5
6
Introduction to thread
0 A thread is a single flow of control like simple program.
0 A unique property of java is multithreading only because java
supports multithreading.
0 More than one thread (program) run simultaneously is known as
multithreading (multiprogramming).
0 In multithreading java interpreter handles the switching of control
between the threads in such a way that it looks like they are running
concurrently.
0 Multithreading is useful in a number of ways. We can divide a long
program into number of threads and executes them in parallel.
0 We are going to learn so many useful things in thread lets start with
single main thread.

AP - Chapter 5 7
(Thread) 6
Application Thread
0 When we execute an application:
1. The JVM creates a Thread object whose task is
defined by the main() method
2. The JVM starts the thread
3. The thread executes the statements of the program
one by one
4. After executing all the statements, the method
returns and the thread dies

AP - Chapter 5 8
(Thread) 7
Multiple Threads in an Application
0 Each thread has its private run-time stack
0 If two threads execute the same method, each will have its own copy
of the local variables and the methods
0 However, all threads see the same dynamic memory,
0 Two different threads can act on the same object and same static
fields concurrently

AP - Chapter 5 9
(Thread) 8
The Main Thread
0 When our simple program starts, one single thread begins running
immediately. This is called our single main thread.
0 The main thread is created automatically when program is started.
0 It is very important thread because of two reason.
1. From the main thread other child thread will be created.
2. Main thread is all most every time stop running lastly because it
has to remove or shutdown few resources as well as few action.
0 Now the question is how can we control our main thread?
0 Actually by calling the method currentThread() of Thread class
we can control our main thread.

AP - Chapter 5 1
(Thread) 0 9
The Main Thread(cont)
//A program to find out the thread used by JVM to execute the
statements.
class FirstDemo {
public static void main(String[] args)
{ System.out.println("Let's find current thread..
");
Thread th=Thread.currentThread();
System.out.println("Current thread is: "+th);
System.out.println("Thread name is: "+th.getName());
System.out.println("Thread priority is: "+th.getPriority());
System.out.println("Thread
} is alive: "+th.isAlive());Output
} Let's find current thread..
Current thread is: Thread[main,5,main]
Thread name is: main
Thread priority is: 5 1
Thread is alive: 110
The Main Thread(cont)
EX:
public class SecondDemo {
public static void main(String args[])
{ Thread t =
Thread.currentThread();
System.out.println("Current thread: " +
t);

// change the name of the thread t.setName("My


Thread"); System.out.println("After name
change: " + t); try {
for(int n = 5; n > 0; n--) {
System.out.println(n); //print number
with interval of 1 sec. Thread.sleep(1000);//Thread is going
to sleep for 1 sec.
}
} catch (InterruptedException e)
{ System.out.println("Main thread
interrupted");
} AP - Chapter 5 1
} (Thread) 211
The Main Thread(cont)
Output:
Current thread: Thread[main,5,main]
After name change:
Thread[My Thread,5,main] 5
4
3
2
1

0 Here first of all we give


reference of our current main single thread to
t by thread object and
currentThread() method.
0 The number 5 to 1 will be print
at interval of 1 second due to sleep
method.
0 Thread will go to sleep for
1000 milliseconds due to sleepAPmethod
- Chapter 5 1
(Thread) 312
Thread Life Cycle
0 Thread has many different state through out its life.
1. Newborn State
2. Runnable State
3. Running State
4. Blocked State
5. Dead State
0 Thread should be in any one state of the above and it can be move
from one state to another by different methods and ways.

AP - Chapter 5 1
(Thread) 413
Thread Life Cycle(cont)

AP - Chapter 5 1
(Thread) 514
Thread Life Cycle(cont)
1) Newborn State
0 When we create a thread it will be in Newborn State.
0 The thread is just created still its not running.
0 We can move it to running mode by invoking the start() method and
it can be killed by using stop() method.

AP - Chapter 5 1
(Thread) 615
Thread Life Cycle(cont)
2) Runnable State
0 It means that thread is now ready for running and its waiting to give
control.
0 We can move control to another thread by yield() method.

AP - Chapter 5 1
(Thread) 716
Thread Life Cycle(cont)
3) Running State
0 It means thread is in its execution mode because the control of CPU
is given to that particular thread.
0 It can move in three different situation from running mode.

AP - Chapter 5 1
(Thread) 817
Thread Life Cycle(cont)
4) Blocked State
0 A thread is called in Blocked State when it is not allowed to entering
in Runnable State or Running State.
0 It happens when thread is in waiting, suspended or in sleeping
mode.

5) Dead State
0 When a thread is completed executing its run() method the life cycle
of that particular thread is end.
0 We can kill thread by invoking stop() method for that particular
thread and send it to be in Dead State.

AP - Chapter 5 20
(Thread) 18
Thread Methods
void start()
0 Creates a new thread and makes it runnable
0 This method can be called only once
void run()
0 The new thread begins its life inside this method
void stop() (deprecated)
0 The thread is being terminated
void yield()
0 Causes the currently executing thread object to temporarily pause
and allow other threads to execute
0 Allow only threads of the same priority to run
void sleep(int m) or sleep(int m, int n)
0 The thread sleeps for m milliseconds, plus n nanoseconds

2
119
Creating Thread
0 We can create thread in java with two different ways.
1. Extending the Thread Class.
2. Implements runnable interface.
0 Let’s try to understand step by step both of this.

AP - Chapter 5 22
(Thread) 20
Creating Thread(cont)
1. Extending the Thread class:
0 In this method one normal class extends the inbuilt class thread and
override its run() method with the code required by that particular
thread.
0 Here we are going to extend class java.lang.Thread. so we can access
all the methods of thread class.
0 Create one class which extends the thread class.
0 Override the run method and put lines of code inside thread method
that will be perform by thread.
0 Create an object of class which we created with extending the thread
class and call the start() method to execute the thread.

AP - Chapter 5 23
(Thread) 21
Creating Thread(cont)
0 Let’s have a thread named MyThread.
Class MyThread extends Thread {
………………..
………………..
}
0 Implementing the run() method
Public void run() {
………
// Thread code here
}
0 Starting new Thread
MyThread aTh = new
MyThread(); // instantiates a
new object aTh
aTh.start(); // invokes
AP - Chapter 5 24
run() method (Thread) 22
Creating Thread(cont)
public class ThirdDemo extends Thread{
public static void main(String[] a) {
ThirdDemo t = new ThirdDemo ();
t.start();
System.out.println("Hello world! -
From the main program.");
}
public void run() {
System.out.println("Hello world! - From a thread.");
try {
sleep(1000*60*60);
} catch (InterruptedException e)
{ System.out.println("Interrupted."
);
}
}
}
Output:
Hello world! - From the main program.
AP - Chapter 5 2
Hello world! - From a thread. (Thread) 5 23
Creating Thread(cont)
0 A couple of things you should know about this program:
 This program will run (actually sleep) for about one hour, after printing those
messages. So you may need to press Ctrl-C to terminate the program.
 There will be actually two threads running in this program. The first one is
the main thread executing all the statement in the main() method. The
second one is a sub-thread launched by the t.start() statement. The sub-
thread executes all the statements in the run() method.
 Notice the order of the messages printed out on the console. It tells us that
the sub-thread took a little bit longer to run its first statement, after it has
been launched by the main thread.
 A multi-threading program will not terminate until all its threads has reached
the end of their execution. In our example, the main thread will end after
printing its message. But the sub-thread will need about one hour to execute
the sleep() call statement. So the entire program will not terminate until the
sub-thread ends.
 The run() method in the Thread is empty, so if you want a thread to do some
work, you need to override the run() method.
AP - Chapter 5 (Thread)
24
26
Creating Thread(cont)
import java.lang.Thread;
class A extends Thread{
public void run()
{ System.out.println("Thread
A"); for(int i=1;i<=5;i++){
System.out.println("From
thread A i = " + i);
}
System.out.println("Exit from A");
}
}
class B extends Thread {
public void run(){
System.out.println(
"Thread B");
for(int i=1;i<=5;i+
+){
System.out.pri
ntln("Fro
m thread 2
7 25
Bi="+
public class FourthDemo {Creating Thread(cont)
public static void main(String[] args) {
//A a = new A().start();
//or
//A a = new A();
//a.start();
//or
new A().start();//creating A class thread object and calling run method
new B().start();//creating B class thread object and calling run
method
System.out.println("End of main thread"); Thread A
From thread A i = 1
} From thread A i =
} 2
From thread A i = 3
From thread A i =
4
From thread A i = 5
Exit from A
End of main thread
Thread B
From thread B i = 1
From thread B i = 2
AP - Chapter 5 From thread2 B i =
(Thread) 8 26
3 From thread Bi
Creating Thread(cont)
Output 2 0 Here you can see that both outputs are different
Thread A
From though our program code is same.
thread A i = 1 0 It happens in thread program because they
From thread A i = 2
End of main are running concurrently on their own.
thread From 0 Threads are running independently of one another
thread A i = 3
From thread A i = 4 and each executes whenever it has a chance.
Thread B
From
thread A i = 5
From thread B i = 1
Exit from A
From
thread B i = 2
From
thread B i = 3
From thread B i = 4
From thread B i =
5 Exit from B
AP - Chapter 5 29
(Thread) 27
Creating Thread(cont)
2) Implementing the Runnable interface:
0 In this method we have one interface named runnable and we
implements this interface for implementing a thread.
0 Create one class which implements runnable interface.
0 Override the run() method and put some line of code for that
particular thread.
0 Now create an object of inbuilt thread class and create an object of
class that implements runnable interface.
0 Give the reference of object to thread object by passing an argument
(argument must be the object of class which implements the
runnable interface) while creating a thread object.
0 Call the start() method to run the thread.

AP - Chapter 5 30
(Thread) 28
Creating Thread(cont)
class FifthDemo implements Runnable {
public static void main(String[] a) {
FifthDemo r = new FifthDemo();
Thread t = new Thread(r);
t.start();
System.out.println("Hello world! -
From the main program.");
}
public void run() {
System.out.println("Hello world! - From a thread.");
try {
Thread.sleep(1000*60*60);
} catch (InterruptedException e)
{ System.out.println("Interrupted."
);
}}
} Output:
Hello world! - From the main program.
Hello world! - From a thread.
AP - Chapter 5 3
(Thread) 129
Creating Thread(cont)
0 Note that:
 The program behaves the same way as the previous program
ThirdDemo which is created using thread objects with thread sub
classes
 The Thread object t is created with the special Thread constructor,
which takes a Runnable object as input. If you start a Thread object
created in this way, the run() method of the Runnable object will be
executed as a new thread.
 Since our class is not extending the Thread class any more, we need to
call the sleep() explicitly by prefixing the class name: Thread.
0 May be you are wondering why we need the second way of creating a new
thread, which seems to be less straight forward than the first way? The
answer is that Java classes can not be extended from two different base
classes. So if you are in a situation where you want to create a new class by
extending an existing class to inherit some nice features of that class, and
you also want to make the new class executable as a thread, you have to use
the second way to implement the "Runnable" interface in your new class.
AP - Chapter 5 (Thread) 30
Creating Thread(cont)
Output
class X implements Runnable { End of main Thread
public void run() { Inside X thread
From xthread i = 1
System.out.println("Inside X thread");
From xthread i = 2
for(int i=1;i<=10;i++) { From xthread i = 3
System.out.println("From xthread i = From xthread i = 4
" +i); From xthread i = 5
} From xthread i = 6
System.out.println("Exit from X"); From xthread i = 7
} From xthread i = 8
} From xthread i = 9
From xthread i = 10
public class SixthDemo{
Exit from X
public static void main(String[] args) {
X x1 = newthread
//creating X(); object
//classand
object
giving reference of class object to thread
object Thread xthread = new Thread(x1);
xthread.start();
System.out.println("End of main Thread");
}
}
AP - Chapter 5 33
(Thread) 31
Extending Thread vs. Implementing
Runnable Interface
0 •Choosing between these two is a matter of taste
0 •Implementing the Runnable interface
0 May take more work since we still
 •Declare a Thread object
 •Call the Thread methods on this object
0 Your class can still extend other class
0 •Extending the Thread class
0 Easier to implement
0 Your class can no longer extend any other class

AP - Chapter 5 34
(Thread) 32
The Thread Class: Constructor

AP - Chapter 5 3
(Thread) 5 33
The Thread Class: Constants
0 Contains fields for priority values

AP - Chapter 5 36
(Thread) 34
The Thread Class: Methods
0 Some Thread methods

AP - Chapter 5 3
(Thread) 7 35
Thread Priority
0 Each java thread has its own priority which decides the order of
thread to be schedule.
0 The threads of equal priority will be given same treatment by
java
scheduler. And they will follow the FCFS (First Come First Serve)
algorithm.
0 User can also set the priority of thread by using the setPriority()
method as follow:
ThreadName.setPriority(int Number);
0 Here the number is integer value between 1 to 10, Here 1 is
minimum priority 10 is maximum priority.
0 The Thread class defines few priority constants:
0 MIN_PRIORITY = 1
0 NORM_PRIORITY = 5
0 MAX_PRIORITY = 10
0 In any Thread the default priority is NORM_PRIORITY
AP - Chapter 5 (Thread) 36
Thread Priority(cont)
0 In multithreading by assigning priority we can answer an
input as quickly as we want.
0 Whenever more than one threads are ready to run java
system select the highest priority thread and execute it
0 If another thread of higher priority comes ,the running
thread will be preempted(blocked) by the incoming thread
and current thread will move to runnable state.

AP - Chapter 5 39
(Thread) 37
Thread Priority(cont)
class TA extends Thread {
public void run() {
System.out.println("ThreadTA strated");
for(int i = 1; i<=5; i++) {
System.out.println("\t From ThreadTA i
= " +i);
}
System.out.println("Exit from TA");
}
}
class TB extends Thread
{ public void run() {
System.out.println("ThreadTB strated");
for(int j = 1; j<=5; j++) {
System.out.println("\t From ThreadTB j
= " +j);
}
} System.out.println("Exit from AP -TB");
Chapter 5 40
} (Thread) 38
Thread Priority(cont)
public class SeventhDemo {
public static void main(String[] args)
{ TA threadTA = new TA();
TB threadTB = new TB();
Output
Start Thread TA
threadTA.setPriority(Thread.MIN_PRIORITY); Start Thread TB
threadTB.setPriority(threadTA.getPriority()+3); ThreadTA strated
End of main Thread
From
System.out.println("Start Thread TA"); ThreadTA i = 1
threadTA.start(); From ThreadTA i = 2
From ThreadTA i =
3 From ThreadTA i
System.out.println("Start Thread = 4 From ThreadTA
TB"); threadTB.start(); i=5
Exit
from TA
System.out.println("End of main Thread"); ThreadTB strated
} From
} ThreadTB j = 1
From ThreadTB j = 2
AP - Chapter 5 4
From ThreadTB
139
j=
(Thread)
3 From ThreadTB j
Thread Priority(cont)
0 In the previous example you can see that we start
ThreadTA first but ThreadTB completed its task first
because of higher priority.
0 But again it is multithreading so we all know that output
may be vary each time you run the program.

AP - Chapter 5 4
(Thread) 2 40
41
Race condition & How to Solve it
0 •Race conditions occur when multiple, asynchronously
executing threads access the same object (called a shared
resource) returning unexpected (wrong) results
0 •Example: Threads often need to share a common resource i.e.
a file, with one thread reading from the file while another
thread writes to the file. They can be avoided by
synchronizing the threads which access the shared resource

42
Method one An Unsynchronized Example
class PrintStringsThread implements Runnable {
Thread thread;
String str1, str2;
PrintStringsThread(String str1, String str2) {
this.str1 = str1;
this.str2 = str2;
thread = new java.lang.Thread(this);
thread.start();
}
public void run()
{ System.out.print(this.str
1);
try {
java.lang.Thread.sleep(200
0);
}catch (InterruptedException ie) {

} System.out.println(this.str2);
43
}
Method one An Unsynchronized Example
public class
RaceConditionDemo{ public static
void main(String[] args) {
new PrintStringsThread("Hello ",
“comps.");
new PrintStringsThread("How are ",
"you?");
new PrintStringsThread("Thank you ",
"very much!");
} Hello How are Thank you comps. Hello How are Thank you you?
} you? very much!
very much! comps.
Sample
output
s:
Hello How are Thank you comps. Hello Thank you How are comps.
very much! very much!
you? you?

44
Method two An Unsynchronized Example
public class RaceConditionDemoTwo
{ public static void main(String[] args)
{
new PrintStringsThread2("Hello ",
"comps.").start();
new PrintStringsThread2("How are ",
"you?").start();
new PrintStringsThread2("Thank you
", "very much!").start();
}
}
class PrintStringsThread2 extends Thread {
String str1, str2;
PrintStringsThread2(String str1, String str2) {
this.str1 = str1;
this.str2 = str2;
}
public void run() {
System.out.print(this.str1);
try {
java.lang.Thread.sleep(2000); 45
}catch (InterruptedException ie) {
Unsynchronized Example
0 The biggest problem of allowing multiple threads sharing the same
data set is that one operation in one thread could collide with
another operation in another threads on the same data. When this
happens, the result is un-desirable.
0 Let's use a bank application program as an example. Assuming that
the program has multiple threads running, with each thread
connecting one ATM system, and you have a saving account in the
bank with $100.00, now you and your friend are going to two
different ATMs at about the same time, and trying to withdraw
$50.00 from your account, what do you think it will happen?
0 If the threads are running independently, the following could
happen:

46
Unsynchronized Example

0 Both you and your friend will receive $50.00 each, and your
account will still have $50.00. The bank could lose $50.00.
0 The solution to this problem is synchronization.
47
Synchronization: Locking an Object
0 •Synchronization is needed in a multi-threading application to
ensure that one thread is updating a shared data other threads wait
and get the updated value.
0 Synchronization uses a lock to represent the shared data to allow
each thread to use the lock status to Synchronize with each other.
0 Synchronization code block is a unit of code in a thread that
requires synchronization on a particular lock.
0 More synchronization locks or longer synchronization code blocks
slow down application performance.
0 A thread is synchronized by becoming an owner of the object's
monitor
0 Consider it as locking an object
0 •A thread becomes the owner of the object's monitor in one of these
ways
0 Option 1: Use synchronized method
0 Option 2: Use synchronized statement on a common object
48
Synchronization: Locking an Object
0 Synchronization is a programming technique that involves 3 elements:
 Lock: An object with two states: locked and unlocked.
 Synchronized Block: A block of statements that is associated with a
lock.
 Synchronization Rule: When a synchronized block is encountered in
a thread of execution, the associated lock will be checked. If the lock
locked, the execution will be stopped until the lock is unlocked. If the
lock is unlocked, the lock will be locked, and the synchronized block of
statements will be executed. When the execution reaches the end of
the synchronized block, the lock will be unlocked. With this rule, two
synchronized blocks associated with same lock will never be executed
at the same time.
0 Now let's see if we can use the synchronization technique in the bank
application program to help the bank. Let's define a synchronization
block starting from the "Get Account Balance" action to the "Set Account
Balance" action in each thread, and associate the block with a lock. With
this change, both you and your friend can still withdraw $50.00, but your
account will have nothing left: 49
Synchronization: Locking an Object

0 The synchronization technique did help the bank from losing money. But
it also increased the total transaction time.
50
How Java Supports Synchronization?
0 Instead of let the programmers to design their own locks, manage the
synchronization blocks, and apply the synchronization rules, Java
offers a synchronization monitor on each instance of the Object class,
so it can be used as a synchronization lock. Since all classes are sub
classes of Object, all objects in Java can be used as synchronization
locks.
0 Java also offers three ways to define synchronized blocks.

51
How Java Supports Synchronization?
Way 1) Synchronized Class Method:
class class_name {
static synchronized return_type method_name() {
//statement block
}
}
0 All the statements in the method become the synchronized block, and
the class object is the lock.

52
How Java Supports Synchronization?
Way 2) Synchronized Instance Method:
class class_name {
synchronized return_type method_name() {
//statement block
}
}
0 All the statements in the method become the synchronized block, and
the instance object is the lock.

53
How Java Supports Synchronization?
Way 3) Synchronized Statement:
class class_name {
return_type method_name() {
synchronized (object) {
statement block
}
}
}
0 All the statements specified in the parentheses of the synchronized
statement become the synchronized block, and the object specified in
the statement is the lock.

54
How Java Supports Synchronization?
0 For example, the following code defines two synchronized blocks. Both
are associated with the same lock, the instance object.

class class_name {
type method_name() {
synchronized (this) {
statement block 1
}
}
synchronized type method_name() {
statement block 2
}
}
0 Block 1 will never be executed at the
same time as block 2.
55
How Java Supports Synchronization?
0 The following code defines two synchronized blocks. But they are
associated with two different locks, one is the class object, and the
other is the instance object.

class class_name {
type method_name() {
synchronized (this) {
statement block 1
}
}
static synchronized type method_name() {
statement block 2
}
}
0 The two synchronized blocks will never wait
for each other.
56
How Java Supports Synchronization?
0 Exercise: Assuming the following class is used in a multiple-threaded
program:

public class C {
public static synchronized void m1() {
statement block_1
}
public synchronized void m2() {
statement block_2
}
public synchronized void m3() {
statement block_3
}
public void m4() {
synchronized (this) {
statement block_4
}
}
}
57
Deposit as a Synchronized
method
0 Assume we have a method called deposit in Account class. So here is
how to make it synchronized.

class Account {
int balance=0;

public synchronized void deposit(int amount) {

int tmp = balance;


Thread.sleep(200);
balance = tmp + amount;

System.out.println("Current balance is
"+balance);
}
}//Account

58
Option 1: Use synchronized method
class TwoStrings {
synchronized static void print(String str1, String str2) {
System.out.print(str1);
try {
Thread.sleep(500);
} catch (InterruptedException ie) {

} System.out.println(str2);
}
}
class PrintStringsThread implements Runnable {
Thread thread;
String str1, str2;
PrintStringsThread(String str1, String str2) {
this.str1 = str1;
this.str2 = str2;
thread = new Thread(this);
thread.start();
}
public void run()
{ TwoStrings.print(str1,
str2); 59
}
Option 1: Use synchronized method
public class SynchDemoOne {
public static void main(String[] args) {
new PrintStringsThread("Hello ", "comps.");
new PrintStringsThread("How are ", "you?");
new PrintStringsThread("Thank you ", "very
much!");
}
}

Output
Hello comps.
How are you?
Thank you
very much!

60
Option 2: Use synchronized statement on a common object
class TwoStrings {
static void print(String str1, String str2) {
System.out.print(str1);
try {
Thread.sleep(500);
} catch (InterruptedException ie) {

} System.out.println(str2);
}
}
class PrintStringsThread implements
Runnable {
Thread thread;
String str1, str2;
TwoStrings ts;
PrintStringsThread(String str1, String str2, TwoStrings ts)
{ this.str1 = str1;
this.str2 = str2;
this.ts = ts;
thread = new Thread(this);
thread.start();
}
public void run()
{ synchronized
(ts) { ts.print(str1,
str2);
61
Option 2: Use synchronized statement on a common object
public class SynchDemoTwo {
public static void main(String[] args) {
TwoStrings ts = new TwoStrings();
new PrintStringsThread("Hello ", "comps.", ts);
new PrintStringsThread("How are ", "you?", ts);
new PrintStringsThread("Thank you ", "very
much!", ts);
}
}

Output
Hello comps.
How are you?
Thank you very
much!

62
?????

63

You might also like