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

Java Thread Management Techniques

The document provides an overview of advanced software development concepts in Java, focusing on threading, concurrency, and design patterns. It covers the thread life cycle, Runnable interface, active objects, double-checked locking, volatile variables, and the use of executors and thread pools. Additionally, it discusses the Future interface for asynchronous computation and the guarded suspension pattern for managing operations with preconditions.

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 views37 pages

Java Thread Management Techniques

The document provides an overview of advanced software development concepts in Java, focusing on threading, concurrency, and design patterns. It covers the thread life cycle, Runnable interface, active objects, double-checked locking, volatile variables, and the use of executors and thread pools. Additionally, it discusses the Future interface for asynchronous computation and the guarded suspension pattern for managing operations with preconditions.

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

In Java

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


Computer
Science
School

The Thread Life Cycle


A
Blocked

Scheduler choice
Ready Queue
End of Time slice Running
Born C
C
C Dead
B
[Link](x)

Sleep
[Link]()

Wait

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


Computer
Science
School

Thread & Runnable


<<Runnable>>
void run()

Thread
Runnable r;
void run() {
[Link]();
}
void start() Tells the JVM to execute run() in a thread
… i.e., run() enters the Ready Queue

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


Computer
Science
School

Option 1: extending Thread

Thread
run()
start()
1. Extended the Thread class
2. Override the run() method
3. Call start to execute in parallel
MyTask

run(){ doTask(); }

But sometimes our class is not a type of Thread or it already extends something else
Advanced Software Development 2, Dr. Eliahu Khalastchi, 2017 ©
Computer
Science
School

Option 2: implementing Runnable

Thread <<Runnable>>
start() run()
1. Implement the Runnable interface
2. Create an instance of Thread
3. Inject the Runnable
4. Call start
MyTask

run(){ doTask(); }

This is a typical strategy pattern, but what if we don’t want to (or can’t) change MyTask?
Advanced Software Development 2, Dr. Eliahu Khalastchi, 2017 ©
Computer
Science
School

Option 3: using object adapters!

Thread <<Runnable>> Thread t=new Thread(new TaskRunnable(new MyTask()));


start() run() [Link]();

TaskRunnable
<<Task>>
Task t; doTask()
run(){ [Link](); }

MyTask

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


Computer
Science
School

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


Computer
Science
School

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


Computer
Science
School

Active Object
 Decouples method execution from method invocation
 for objects that each reside in their own thread of control

 The goal is to introduce concurrency,


 by using asynchronous method invocation
 and a scheduler for handling requests

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


Computer
Science
School

Example
class MyModel implements Model{

Maze maze;
Solution solution;
Not an active object
void generateMaze(){ Method invocation is coupled to execution
maze=[Link](/**/);
}

void solve(Maze m){


solution=[Link](m);
}
}

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


Computer
Science
School

Example AMI – asynchronous method invocation


class MyActiveModel implements Model { void generateMaze() throws InterruptedException {
[Link](new Runnable() {
Maze maze; public void run() {
Solution solution; maze = [Link](/**/);
BlockingQueue<Runnable> dispatchQueue }
= new LinkedBlockingQueue<Runnable>(); });
}
public MyActiveModel() {
void solve(Maze m) throws InterruptedException {
new Thread(new Runnable() { [Link](new Runnable() {
public void run() { public void run() {
while (true) { solution = [Link](m);
try { }
// take() blocks, so no busy waiting });
[Link]().run(); }
} catch (InterruptedException e) {}
}
}
}).start();

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

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


Computer
Science
School

Double-checked locking
 Goal: to reduce the overhead of acquiring a lock
 by first testing the locking
 without actually acquiring the lock

 Only if the locking is required then do the actual locking

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


Computer
Science
School

Example - Singleton

class Foo {
private Helper helper;
public Helper getHelper() {
if (helper == null) {
helper = new Helper();
}
return helper;
}
}

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


Computer
Science
School

Example - Singleton
class Foo {
private Helper helper;
public synchronized Helper getHelper() {
if (helper == null) {
helper = new Helper();
}
return helper;
}
}

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


Computer
Science
School

Example - Singleton
class Foo {
private Helper helper;
public Helper getHelper() {
if (helper == null) {
synchronized(this) {
if (helper == null) {
helper = new Helper();
}
}
}
return helper;
}
}

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


Computer
Science
School

Example - Singleton
class Foo {
private Helper helper; helper
public Helper getHelper() {
if (helper == null) {  Thread B
synchronized(this) {
if (helper == null) {
helper = new Helper();  Thread A Helper
}
}
}
return helper;
}
}

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


Computer
Science
School

Volatile
 Every read & write to a volatile variable will be on the main memory
 Not the CPU cache…

CPU 1 CPU 1 Main


Cache Memory
Thread A c=7
c=0
c=0
c=7 // none volatile
CPU 2 CPU 2
Cache
Thread B c=0

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


Computer
Science
School

Volatile
 Every read & write to a volatile variable will be on the main memory
 Not the CPU cache…

CPU 1 CPU 1 Main


Cache Memory
Thread A
c=0
c=7 // volatile
CPU 2 CPU 2
Cache
Thread B

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


Computer
Science
School

Volatile: Happens-Before Guarantee


 Every read & write to a volatile variable will be on the main memory
 Not the CPU cache…

 When a thread reads or writes to a volatile variable


 all other dependent variables are flushed to main memory as well

 Reading and writing instructions cannot be reordered by the JVM

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


Computer
Science
School

Example - Singleton
class Foo {
private volatile Helper helper; helper = null
public Helper getHelper() {
if (helper == null) {  Thread B
synchronized(this) {
if (helper == null) {
helper = new Helper();  Thread A Helper
}
}
}
return helper;
}
}

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


Computer
Science
School

Example - Singleton
class Foo{
private volatile Helper helper;
public Helper getHelper() {
Helper result = helper;
if (result == null) {
synchronized(this) {
result = helper;
if (result == null) {
helper = result = new Helper();
}
}
}
return result; As much as 25% performance improvement
}
}
Advanced Software Development 2, Dr. Eliahu Khalastchi, 2017 ©
Computer
Science
School

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


Computer
Science
School

Example - Singleton
class Foo{
“Eager” instead of “Lazy”

private static final Helper helper = new Helper();

public static Helper getHelper() {


return helper;
}
}

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


Computer
Science
School

Example - Singleton
class Foo{
private static class HelperHolder {
public static final Helper helper = new Helper();
}

public static Helper getHelper() {


return [Link];
} inner classes are not loaded until they are referenced
}

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


Computer
Science
School

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 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 ());
task1 started }
task2 started
task1 finished
task2 finished
task3 started
task3 finished

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


Computer
Science
School

Thread Pool
 Control the number of threads
 No thread creation / destruction overhead
// a thread that can run task after task
class PooledThread extends Thread{
Runnable task;
Object lock;
boolean terminated=false;

public void assignTask(Runnable r){


task=r;
unSuspendMe();
}
public void run(){
while(!terminated){
[Link]();
suspendMe();
}
} // the pooled thread dies
// ...
Advanced Software Development 2, Dr. Eliahu Khalastchi, 2017 ©
Computer
Science
School

• doesn't block the calling thread while waiting for a reply


• Instead, the calling thread is notified when the reply arrives
• Polling for a reply is an undesired option.

• One common use of AMI is in the active object design pattern


• Alternatives are synchronous method invocation and future objects.

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


Computer
Science
School

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

 A Callable Interface can }

 ExecutorService (a type of thread pool) 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. The submit() method was written years ago… the Worker class 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);
V get();
Worker call() throws Exception{
// 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

Guarded suspension pattern


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

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


Computer
Science
School

Guarded Suspension
 Manages operations that require both
 a lock to be acquired public class GameCharacter {
boolean victory;
 and a precondition to be satisfied int score;
 before the operation can be executed synchronized void victoryDance() { // guarded method
while (!victory) {
try { wait();} catch (InterruptedException e) {}
}
// Actual task implementation
// victory dance!!
}

synchronized void updateScore(int x) {


// ...
// Inform waiting threads
notify();
}
}

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

You might also like