0% found this document useful (0 votes)
5 views28 pages

Advanced Java Thread Management Techniques

The document discusses advanced software development techniques in Java, particularly focusing on thread management and concurrency. It covers tools from the java.util.concurrent package, scheduling tasks with sleep and timers, using synchronized methods versus atomic variables, and avoiding deadlocks with tryLock(). Additionally, it introduces the Executor interface, thread pools, Callable and Future for managing tasks and their results in a multi-threaded environment.

Uploaded by

Roy Ancri
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
5 views28 pages

Advanced Java Thread Management Techniques

The document discusses advanced software development techniques in Java, particularly focusing on thread management and concurrency. It covers tools from the java.util.concurrent package, scheduling tasks with sleep and timers, using synchronized methods versus atomic variables, and avoiding deadlocks with tryLock(). Additionally, it introduces the Executor interface, thread pools, Callable and Future for managing tasks and their results in a multi-threaded environment.

Uploaded by

Roy Ancri
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

Computer

Science
School

Dr. Eliahu Khalastchi


2017

Advanced Software Development 2, Dr. Eliahu Khalastchi, 2017 ©


Computer
Science
School

Introduction
 By now, you know how to program threads
 But in a very basic level that matches low-level implementations
 For higher-level code, we need advanced tools
 Tools that will hide the threads logic from us
 Makes it easier for us to control threads
 Mostly are from [Link]
 introduced in java 1.5

Advanced Software Development 2, Dr. Eliahu Khalastchi, 2017 ©


Computer
Science
School

With simpler tools…

Advanced Software Development 2, Dr. Eliahu Khalastchi, 2017 ©


Computer
Science
School

Scheduling
 We can use sleep() & wait() to influence thread scheduling

Blocked

Scheduler choice
Ready Queue
End of Time slice Running
Born Dead

[Link](x)

Sleep
[Link]()

Wait
Advanced Software Development 2, Dr. Eliahu Khalastchi, 2017 ©
Computer
Science
School

Scheduling Tasks
public class Ping implements Runnable{
 We want an ordered
public void run(){while(true)[Link]("ping");} “ping-pong” sequence
}  Half a second apart
public class Pong implements Runnable{  Does this code meet the
public void run(){while(true)[Link]("pong");} demands?
}
public static void main(String[] args) {
Ping ping=new Ping();
Pong pong=new Pong();
Thread t=new Thread(ping,"thread 1");
Thread t1=new Thread(pong,"thread 2");
[Link]();
[Link]();
}
Advanced Software Development 2, Dr. Eliahu Khalastchi, 2017 ©
Computer
Science
School

Scheduling Tasks
 Here is a solution using sleep()
public class Ping implements Runnable{ public static void main(String[] args) throws InterruptedException {

public void run(){ Ping ping=new Ping();

while(true){ Pong pong=new Pong();

[Link]("ping"); Thread t=new Thread(ping,"thread 1");

try {[Link](1000);} Thread t1=new Thread(pong,"thread 2");

catch (InterruptedException e) {} [Link]();

} [Link](500); // the main sleeps 0.5 sec

} [Link]();

} }

// pong is the same…

Advanced Software Development 2, Dr. Eliahu Khalastchi, 2017 ©


Computer
Science
School

Scheduling Tasks – with a simple Timer!


import [Link];
import [Link];
public class ThreadTest {
private static class Ping extends TimerTask{
public void run(){[Link]("ping");}
}
Canceling tasks:
private static class Pong extends TimerTask{
int i;
public void run(){[Link]("pong");}
} while((i=[Link]())!=13);
public static void main(String[] args){ [Link](); // canceled task
Ping ping=new Ping(); [Link](); // t continues…
Pong pong=new Pong(); [Link](); // t is cancled
Timer t=new Timer();
[Link](ping, 0, 1000);
[Link](pong, 500, 1000);
}
}
Advanced Software Development 2, Dr. Eliahu Khalastchi, 2017 ©
Computer
Science
School

With faster / none-blocking locks

Advanced Software Development 2, Dr. Eliahu Khalastchi, 2017 ©


Computer
Science
School

Using Synchronized is slow…


public class Count { public static void main(String[] args) {
private int count; Count c=new Count();
public void setCount(int x){count=x;} [Link](0);
public int getCount(){return count;} CountUpdater ca=new CountUpdater(c);
public synchronized void update(){count++;} Thread t=new Thread(ca);
} Thread t1=new Thread(ca);
long time=[Link]();
public class CountUpdater implements Runnable{ [Link]();
Count c; [Link]();
public CountUpdater(Count c){this.c=c;} [Link]();
public void run(){ [Link]();
for(int i=0;i<100000000; [Link](),i++); [Link]([Link]());
} long duration=([Link]()-time)/1000;
} [Link](duration);
}

Advanced Software Development 2, Dr. Eliahu Khalastchi, 2017 ©


Computer
Science
School

Using Atomic Variables


import [Link]; public static void main(String[] args) {
public class Count { Count c=new Count();
AtomicInteger count = new AtomicInteger(0); [Link](0);
public void setCount(int x){[Link](x);} CountUpdater ca=new CountUpdater(c);
public int getCount(){return [Link]();} Thread t=new Thread(ca);
public void update(){ Thread t1=new Thread(ca);
[Link]();// ++count long time=[Link]();
} [Link]();
} [Link]();
public class CountUpdater implements Runnable{ [Link]();
Count c; [Link]();
public CountUpdater(Count c){this.c=c;} [Link]([Link]());
public void run(){ long duration=([Link]()-time)/1000;
for(int i=0;i<100000000; [Link](),i++); [Link](duration);
} }
}
Advanced Software Development 2, Dr. Eliahu Khalastchi, 2017 ©
Computer
Science
School

And how to avoid it…

Advanced Software Development 2, Dr. Eliahu Khalastchi, 2017 ©


Computer
Science
School

Deadlock Example
Object R=new Object();// readers lock
Object W=new Object();// writers lock

new Thread(new Runnable() { new Thread(new Runnable() {


@Override @Override
public void run() { public void run() {

synchronized (W) { synchronized (R) {


// do the writing... // do the reading...
synchronized (R) { synchronized (W) {
// do some reading... // do some writing...
} }
// do more writing... // do more reading...
} }
} }
}).start(); }).start();
Advanced Software Development 2, Dr. Eliahu Khalastchi, 2017 ©
Computer
Science
School

Deadlock avoidance with tryLock()


Import [Link]; public void run() {
boolean w=[Link]();
ReentrantLock W=new ReentrantLock(); boolean r=[Link]();
ReentrantLock R=new ReentrantLock(); try{
if(w && r){
// do the writing...
• reentrantLock allows to use tryLock(); // do some reading...
• It returns true / false // do more writing...
• Instead of just blocking like synchronized… } else{
// try again later...
• Only if we manage to lock both locks }
• We do the reading & writing }finally{
• Else, we try again later if(w) [Link]();
if(r) [Link]();
• Finally, we unlock whatever lock we may have locked }
}
Advanced Software Development 2, Dr. Eliahu Khalastchi, 2017 ©
Computer
Science
School

Executing tasks with different executors!

Advanced Software Development 2, Dr. Eliahu Khalastchi, 2017 ©


Computer
Science
School

Executor Interface
 So far we used threads with Runnable’s
public void run() method
 There is a direct attachment between the task and the thread that runs it…

 Sometimes we want to decouple these two


 Controlling the number of threads
 Scheduling tasks
 etc
interface Executor {
void execute(Runnable r);
 Therefore an Executor Interface was created }

Advanced Software Development 2, Dr. Eliahu Khalastchi, 2017 ©


Computer
Science
School

Executor Implementations Example


interface Executor {
void execute(Runnable r);
}

class DirectExecutor implements Executor{ class ThreadPerTaskExecutor implements Executor{


public void execute(Runnable r) { public void execute(Runnable r) {
[Link](); new Thread(r).start();
} }
} }

And if we wanted to control the number of threads?


Advanced Software Development 2, Dr. Eliahu Khalastchi, 2017 ©
Computer
Science
School

Thread Pool
 We can use a queue
 Each execute puts the runnable at the end
 Only the first n are polled out of the queue
 They are ran via a thread
 When a task has finished, another is polled

 This is called a Thread Pool

 It is commonly used to control the number of threads, clients etc…

 Strong and flexible thread pools are already implemented for us


Advanced Software Development 2, Dr. Eliahu Khalastchi, 2017 ©
Computer
Science
School

Thread Pools Example


public class RunnableTask1 implements Runnable{ import [Link];
public void run(){ import [Link];
[Link]("task1 started"); import [Link];
try { [Link](10000);} //...
catch (InterruptedException e) {} public static void main(String[] args) {
[Link]("task1 finished"); ExecutorService executor =
} [Link]();
} [Link] (new RunnableTask1 ());
// RunnableTask2 & RunnableTask3 are the same… [Link] (new RunnableTask2 ());
[Link] (new RunnableTask3 ());
Executors class has a factory of task1 started }
thread pools. SingleThreadExecutor task1 finished
allows only one thread to be ran at task2 started
a time. What would be the output? task2 finished
task3 started
task3 finished

Advanced Software Development 2, Dr. Eliahu Khalastchi, 2017 ©


Computer
Science
School

Thread Pools Example


public class RunnableTask1 implements Runnable{ import [Link];
public void run(){ import [Link];
[Link]("task1 started"); import [Link];
try { [Link](10000);} //...
catch (InterruptedException e) {} public static void main(String[] args) {
[Link]("task1 finished"); ExecutorService executor =
} [Link](2);
} [Link] (new RunnableTask1 ());
// RunnableTask2 & RunnableTask3 are the same… [Link] (new RunnableTask2 ());
[Link] (new RunnableTask3 ());
How about now? task1 started }
task2 started
task1 finished
task2 finished
task3 started
task3 finished

Advanced Software Development 2, Dr. Eliahu Khalastchi, 2017 ©


Computer
Science
School

Thread Pools Example


public class RunnableTask1 implements Runnable{ import [Link];
public void run(){ import [Link];
[Link]("task1 started"); import [Link];
try { [Link](10000);} //...
catch (InterruptedException e) {} public static void main(String[] args) {
[Link]("task1 finished"); ExecutorService executor =
} [Link]();
} [Link] (new RunnableTask1 ());
// RunnableTask2 & RunnableTask3 are the same… [Link] (new RunnableTask2 ());
[Link] (new RunnableTask3 ());
How about now? task1 started }
task2 started
task3 started
task1 finished
task3 finished
task2 finished

Advanced Software Development 2, Dr. Eliahu Khalastchi, 2017 ©


Computer
Science
School

Callable
 Runnabler’s run() method
interface Callable<V> {
 Cannot return a value
V call() throws Exception;
 Cannot throw an exception
}
 A Callable Interface can

 ExecutorService can
 execute(Runnable r); // as we have seen
 submit(Callable c);
 It puts the callable in the thread pool and immediately returns
 What can be returned by submit?

Advanced Software Development 2, Dr. Eliahu Khalastchi, 2017 ©


Computer
Science
School

The problem
public class MyCallable implements Callable<Worker>{

Worker call() throws Exception{


// after 10 minutes or so…
return someWorker;
}
}

ExecutorService executor = Executors. newFixedThreadPool (2);


___________ = [Link] (new MyCallable ());

1. submit() was written years ago… Worker was created just now…
2. submit() should return a value now! And not in 10 minutes

Advanced Software Development 2, Dr. Eliahu Khalastchi, 2017 ©


Computer
Science
School

The Solution – Future! Future <V>


V value;
 Future is a holder for a value of type <V> set(V v);
V get();

 The submit method returns immediately an instance of Future


 Future<V> submit(Callable<V> callable);
 We should define the same V in the Callable and the Future

 When the Callable’s call() returns <V> it is set in the instance of Future
 Only then, we may get <V>

Advanced Software Development 2, Dr. Eliahu Khalastchi, 2017 ©


Computer
Science
School

The Solution – Future! Future <V>


V value;
public class MyCallable implements Callable<Worker>{ set(V v);
Worker call() throws Exception{
V get();
// after 10 minutes or so…
return someWorker;
}
}

ExecutorService executor = Executors. newFixedThreadPool (2);

Future<Worker> f = [Link] (new MyCallable ());

Worker w = [Link](); // waits for the call() to return

Advanced Software Development 2, Dr. Eliahu Khalastchi, 2017 ©


Computer
Science
School

Advanced Software Development 2, Dr. Eliahu Khalastchi, 2017 ©


Computer
Science
School

Thread Safe Containers


 Most of [Link] containers are not thread safe
 Because synchronize slows performance
 They could be wrapped with synchronized decorators
 Only when we must, we’ll pay with performance

Map<String,Integer> hm =
[Link](
new HashMap<String,Integer>());

 Decorator Pattern!
 Every method is implemented with synchronized

Advanced Software Development 2, Dr. Eliahu Khalastchi, 2017 ©


Computer
Science
School

Thread Safe Containers


 [Link] introduced Thread Safe containers,
 that also provides good performance!
 ArrayBlockingQueue<E>
 ConcurrentHashMap<K,V>
 ConcurrentLinkedQueue<E>
 etc…

Advanced Software Development 2, Dr. Eliahu Khalastchi, 2017 ©


Computer
Science
School

Now you know how to handle the problems…


private void runServer()throws Exception {
ServerSocket server=new ServerSocket(port);
[Link](1000);
while(!stop){
try{
Socket aClient=[Link](); // blocking call
new Thread(new Runnable() { //WOW! we should control the number of threads!
public void run() {
try {
[Link]([Link](), [Link]());
[Link]().close();
[Link]().close();
[Link]();
} catch (IOException e) {/*...*/}
}
}).start();
}catch(SocketTimeoutException e) {/*...*/}
}
[Link](); //WOW! we should wait for all threads before closing!
}

Advanced Software Development 2, Dr. Eliahu Khalastchi, 2017 ©

You might also like