0% found this document useful (0 votes)
20 views

Threads

Uploaded by

babelneerav299
Copyright
© © All Rights Reserved
Available Formats
Download as PPT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
20 views

Threads

Uploaded by

babelneerav299
Copyright
© © All Rights Reserved
Available Formats
Download as PPT, PDF, TXT or read online on Scribd
You are on page 1/ 68

Java Threads

Representation and Management


of Data on the Internet
Multitasking and Multithreading

• Multitasking refers to a computer's ability to


perform multiple jobs concurrently
– more than one program are running concurrently, e.g.,
UNIX
• A thread is a single sequence of execution within a
program
• Multithreading refers to multiple threads of
control within a single program
– each program can run multiple threads of control within
it, e.g., Web Browser
Concurrency vs. Parallelism
CPU CPU1 CPU2
Threads and Processes
CPU

main

run

Process 1 Process 2 Process 3 Process 4

GC
What are Threads Good For?

• To maintain responsiveness of an
application during a long running task.
• To enable cancellation of separable tasks.
• Some problems are intrinsically parallel.
• To monitor status of some resource (DB).
• Some APIs and systems demand it: Swing.
Application Thread

• When we execute an application:


– The JVM creates a Thread object whose task
is defined by the main() method
– It starts the thread
– The thread executes the statements of the
program one by one until the method returns
and the thread dies
Multiple Threads in an
Application
• Each thread has its private run-time stack
• If two threads execute the same method, each
will have its own copy of the local variables the
methods uses
• However, all threads see the same dynamic
memory (heap)
• Two different threads can act on the same
object and same static fields concurrently
Creating Threads

• There are two ways to create our own


Thread object
1. Subclassing the Thread class and
instantiating a new object of that class
2. Implementing the Runnable interface

• In both cases the run() method should be


implemented
Extending Thread
public class ThreadExample extends Thread {
public void run () {
for (int i = 1; i <= 100; i++) {
System.out.println(“Thread: ” + i);
}
}
}
Thread Methods

void start()
– Creates a new thread and makes it runnable
– This method can be called only once
void run()
– The new thread begins its life inside this
method
void stop() (deprecated)
– The thread is being terminated
Implementing Runnable
public class RunnableExample implements Runnable {
public void run () {
for (int i = 1; i <= 100; i++) {
System.out.println (“Runnable: ” + i);
}
}
}
A Runnable Object

• The Thread object’s run() method calls the


Runnable object’s run() method

• Allows threads to run inside any object,


regardless of inheritance
Example – an applet that is
also a thread
Starting the Threads
public class ThreadsStartExample {
public static void main (String argv[]) {
new ThreadExample ().start ();
new Thread(new RunnableExample ()).start ();
}
}

RESULT
Thread State Diagram
Example
public class PrintThread1 extends Thread {
String name;
public PrintThread1(String name) {
this.name = name;
}
public void run() {
for (int i=1; i<500 ; i++) {
try {
sleep((long)(Math.random() * 100));
} catch (InterruptedException ie) { }
System.out.print(name);
}}
Example (cont)
public static void main(String args[]) {
PrintThread1 a = new PrintThread1("*");
PrintThread1 b = new PrintThread1("-");
PrintThread1 c = new PrintThread1("=");
a.start();
b.start();
c.start();
}
}
RESULT
Scheduling

• Thread scheduling is the mechanism used


to determine how runnable threads are
allocated CPU time
• A thread-scheduling mechanism is either
preemptive or nonpreemptive
Some Notes

• Thread implementation in Java is actually


based on operating system support
• Some Windows operating systems support
only 7 priority levels, so different levels
in Java may actually be mapped to the
same operating system level
• What should we do about this?
Server
import java.net.*;import java.io.*;
class HelloServer {

public static void main(String[] args) {


int port = Integer.parseInt(args[0]);
try {
ServerSocket server =
new ServerSocket(port);
} catch (IOException ioe) {
System.err.println(“Couldn't run “ +
“server on port “ + port);
return;
}
while(true) {
try {
Socket connection = server.accept();
ConnectionHandler handler =
new ConnectionHandler(connection);
new Thread(handler).start();
} catch (IOException ioe1) {
}
}
Connection Handler

// Handles a connection of a client to an HelloServer.


// Talks with the client in the 'hello' protocol
class ConnectionHandler implements Runnable {

// The connection with the client


private Socket connection;

public ConnectionHandler(Socket connection) {


this.connection = connection;
}
public void run() {
try {
BufferedReader reader =
new BufferedReader(
new InputStreamReader(
connection.getInputStream()));

PrintWriter writer =
new PrintWriter(
new OutputStreamWriter(
connection.getOutputStream()));

String clientName = reader.readLine();


writer.println(“Hello “ + clientName);
writer.flush();
} catch (IOException ioe) {}
}
}
Client side
import java.net.*; import java.io.*;

// A client of an HelloServer
class HelloClient {

public static void main(String[] args) {


String hostname = args[0];
int port = Integer.parseInt(args[1]);

Socket connection = null;


try {
connection = new Socket(hostname, port);
} catch (IOException ioe) {
System.err.println("Connection failed");
return;
}
try {
BufferedReader reader =
new BufferedReader(
new InputStreamReader(
connection.getInputStream()));
PrintWriter writer =
new PrintWriter(
new OutputStreamWriter(
connection.getOutputStream()));

writer.println(args[2]); // client name


String reply = reader.readLine();
System.out.println("Server reply: "+reply);
writer.flush();
} catch (IOException ioe1) {
}
}

Note that the Client has not


changed from last week
Concurrency

• An object in a program can be changed by


more than one thread
• Q: Is the order of changes that were
preformed on the object important?
Race Condition

• A race condition – the outcome of a


program is affected by the order in which
the program's threads are allocated CPU
time
• Two threads are simultaneously modifying
a single object
• Both threads “race” to store their value
Race Condition Example

How can we have Put red pieces


Put green pieces
alternating colors?
Monitors

• Each object has a “monitor” that is a token used


to determine which application thread has
control of a particular object instance
• In execution of a synchronized method (or
block), access to the object monitor must be
gained before the execution
• Access to the object monitor is queued
Monitor (cont.)

• Entering a monitor is also referred to as


locking the monitor, or acquiring
ownership of the monitor
• If a thread A tries to acquire ownership
of a monitor and a different thread has
already entered the monitor, the current
thread (A) must wait until the other
thread leaves the monitor
Critical Section

• The synchronized methods define critical


sections
• Execution of critical sections is mutually
exclusive. Why?
Example

public class BankAccount {

private float balance;

public synchronized void deposit(float amount) {


balance += amount;
}

public synchronized void withdraw(float amount) {


balance -= amount;
}
}
t3 t2 t1 Critical Sections

deposit()

Bank Account
Static Synchronized Methods

• Marking a static method as synchronized,


associates a monitor with the class itself
• The execution of synchronized static
methods of the same class is mutually
exclusive. Why?
Example
public class PrintThread2 extends Thread {
String name;
public PrintThread2(String name) {
this.name = name;
}
public static synchronized void print(String name) {
for (int i=1; i<500 ; i++) {
try {
Thread.sleep((long)(Math.random() * 100));
} catch (InterruptedException ie) { }
System.out.print(str);
}
}
Example (cont)
public void run() {
print(name);
}

public static void main(String args[]) {


PrintThread2 a = new PrintThread2("*“);
PrintThread2 b = new PrintThread2("-“);
PrintThread2 c = new PrintThread2("=“);
a.start();
b.start();
c.start();
}
}
RESULT
Deadlock Example
public class BankAccount {

private float balance;

public synchronized void deposit(float amount) {


balance += amount;
}

public synchronized void withdraw(float amount) {


balance -= amount;
}

public synchronized void transfer(float amount,


BankAccount target) {
withdraw(amount);
target.deposit(amount);
}
}
public class MoneyTransfer implements Runnable {

private BankAccount from, to;


private float amount;

public MoneyTransfer(
BankAccount from, BankAccount to, float amount) {
this.from = from;
this.to = to;
this.amount = amount;
}

public void run() {


source.transfer(amount, target);
}
}
BankAccount aliceAccount = new BankAccount();
BankAccount bobAccount = new BankAccount();
...

// At one place
Runnable transaction1 =
new MoneyTransfer(aliceAccount, bobAccount, 1200);
Thread t1 = new Thread(transaction1);
t1.start();

// At another place
Runnable transaction2 =
new MoneyTransfer(bobAccount, aliceAccount, 700);
Thread t2 = new Thread(transaction2);
t2.start();
Deadlocks
t1 t2

aliceAccount bobAccount

transfer() transfer()

?
withdraw() withdraw()

deposit() deposit()
Java Locks are Reentrant

• Is there a problem with the following


code?
public class Test {
public synchronized void a() {
b();
System.out.println(“I am at a”);
}
public synchronized void b() {
System.out.println(“I am at b”);
}
}
Synchronized Statements

• A monitor can be assigned to a block


• It can be used to monitor access to a data
element that is not an object, e.g., array
• Example:
void arrayShift(byte[] array, int count) {
synchronized(array) {
System.arraycopy (array, count,array,
0, array.size - count);
}
}
Thread Synchronization

• We need to synchronized between


transactions, for example, the consumer-
producer scenario
Wait and Notify

• Allows two threads to cooperate


• Based on a single shared lock object
– Marge put a cookie wait and notify Homer
– Homer eat a cookie wait and notify Marge
• Marge put a cookie wait and notify Homer
• Homer eat a cookie wait and notify Marge
The wait() Method

• The wait() method is part of the


java.lang.Object interface

• It requires a lock on the object’s monitor


to execute
• It must be called from a synchronized
method, or from a synchronized segment
of code. Why?
The wait() Method

• wait() causes the current thread to wait


until another thread invokes the notify()
method or the notifyAll() method for this
object
• Upon call for wait(), the thread releases
ownership of this monitor and waits until
another thread notifies the waiting
threads of the object
The wait() Method

• wait() is also similar to yield()


– Both take the current thread off the
execution stack and force it to be
rescheduled
• However, wait() is not automatically put
back into the scheduler queue
– notify() must be called in order to get a
thread back into the scheduler’s queue
Consumer

synchronized (lock) {
while (!resourceAvailable()) {
lock.wait();
}
consumeResource();
}
Producer

produceResource();
synchronized (lock) {
lock.notifyAll();
}
Wait/Notify Sequence

Lock Object
1. synchronized(lock){ 3. produceResource()
2. lock.wait(); 4. synchronized(lock) {
5. lock.notify();
9. consumeResource();
10. } 6.}
7. Reacquire lock
8. Return from wait()
Consumer Producer
Thread Thread
Wait/Notify Sequence

Lock Object
1. synchronized(lock){ 3. produceResource()
2. lock.wait(); 4. synchronized(lock) {
5. lock.notify();
9. consumeResource();
10. } 6.}
7. Reacquire lock
8. Return from wait()
Consumer Producer
Thread Thread
Wait/Notify Sequence

Lock Object
1. synchronized(lock){ 3. produceResource()
2. lock.wait(); 4. synchronized(lock) {
5. lock.notify();
9. consumeResource();
10. } 6.}
7. Reacquire lock
8. Return from wait()
Consumer Producer
Thread Thread
Wait/Notify Sequence

Lock Object
1. synchronized(lock){ 3. produceResource()
2. lock.wait(); 4. synchronized(lock) {
5. lock.notify();
9. consumeResource();
10. } 6.}
7. Reacquire lock
8. Return from wait()
Consumer Producer
Thread Thread
Wait/Notify Sequence

Lock Object
1. synchronized(lock){ 3. produceResource()
2. lock.wait(); 4. synchronized(lock) {
5. lock.notify();
9. consumeResource();
10. } 6.}
7. Reacquire lock
8. Return from wait()
Consumer Producer
Thread Thread
Wait/Notify Sequence

Lock Object
1. synchronized(lock){ 3. produceResource()
2. lock.wait(); 4. synchronized(lock) {
5. lock.notify();
9. consumeResource();
10. } 6.}
7. Reacquire lock
8. Return from wait()
Consumer Producer
Thread Thread
Wait/Notify Sequence

Lock Object
1. synchronized(lock){ 3. produceResource()
2. lock.wait(); 4. synchronized(lock) {
5. lock.notify();
9. consumeResource();
10. } 6.}
7. Reacquire lock
8. Return from wait()
Consumer Producer
Thread Thread
Wait/Notify Sequence

Lock Object
1. synchronized(lock){ 3. produceResource()
2. lock.wait(); 4. synchronized(lock) {
5. lock.notify();
9. consumeResource();
10. } 6.}
7. Reacquire lock
8. Return from wait()
Consumer Producer
Thread Thread
Wait/Notify Sequence

Lock Object
1. synchronized(lock){ 3. produceResource()
2. lock.wait(); 4. synchronized(lock) {
5. lock.notify();
9. consumeResource();
10. } 6.}
7. Reacquire lock
8. Return from wait()
Consumer Producer
Thread Thread
Wait/Notify Sequence

Lock Object
1. synchronized(lock){ 3. produceResource()
2. lock.wait(); 4. synchronized(lock) {
5. lock.notify();
9. consumeResource();
10. } 6.}
7. Reacquire lock
8. Return from wait()
Consumer Producer
Thread Thread
Wait/Notify Sequence

Lock Object
1. synchronized(lock){ 3. produceResource()
2. lock.wait(); 4. synchronized(lock) {
5. lock.notify();
9. consumeResource();
10. } 6.}
7. Reacquire lock
8. Return from wait()
Consumer Producer
Thread Thread
The Simpsons Scenario:
SimpsonsTest
public class SimpsonsTest {

public static void main(String[] args) {

CookyJar jar = new CookyJar();

Homer homer = new Homer(jar);


Marge marge = new Marge(jar);

new Thread(homer).start();
new Thread(marge).start();
}
}
The Simpsons Scenario: Homer
public class Homer implements Runnable {
CookyJar jar;

public Homer(CookyJar jar) {


this.jar = jar;
}

public void eat() {


jar.getCooky("Homer");
try {
Thread.sleep((int)Math.random() * 1000);
} catch (InterruptedException ie) {}
}

public void run() {


for (int i = 1 ; i <= 10 ; i++) eat();
}
}
The Simpsons Scenario: Marge
public class Marge implements Runnable {
CookyJar jar;

public Marge(CookyJar jar) {


this.jar = jar;
}

public void bake(int cookyNumber) {


jar.putCooky("Marge", cookyNumber);
try {
Thread.sleep((int)Math.random() * 500);
} catch (InterruptedException ie) {}
}

public void run() {


for (int i = 0 ; i < 10 ; i++) bake(i);
}
}
The Simpsons Scenario: CookieJar
public class CookyJar {
private int contents;
private boolean available = false;

public synchronized void getCooky(String who) {


while (!available) {
try {
wait();
} catch (InterruptedException e) { }
}
available = false;
notifyAll();
System.out.println( who + " ate cooky " + contents);
}
The Simpsons Scenario: CookieJar
public synchronized void putCooky(String who, int value) {
while (available) {
try {
wait();
} catch (InterruptedException e) { }
}
contents = value;
available = true;
System.out.println(who + " put cooky " + contents +
" in the jar");
notifyAll();
}}
Timers and TimerTask

• The classes Timer and TimerTask are part


of the java.util package
• Useful for
– performing a task after a specified delay
– performing a sequence of tasks at constant
time intervals
Scheduling Timers

• The schedule method of a timer can get


as parameters:
– Task, time
– Task, time, period
– Task, delay
– Task, delay, period
When to start What to do At which rate
Timer Example
import java.util.*;
public class MinchaTask extends TimerTask {
public void run() {
System.out.println(“Time for Mincha!!!!”);
}

public static void main(String args[]) {


Timer timer = new Timer();
long day = 1000 * 60 * 60 * 24;
timer.scheduleAtFixedRate(new MinchaTask(),
new Date(), day);
}
}
Stopping Timers

• A Timer thread can be stopped in the


following ways:
– Apply cancel() on the timer
– Make the thread a daemon
– Remove all references to the timer after all
the TimerTask tasks have finished
– Call System.exit()

You might also like