#Java Multi-Threading Part II
##Lesson4 : Thread Pools
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
/*
* Thread Pools => Managing Lock Threads @ same time
* Thread Pools => Is like how many numbers of worker in your factory
* Run Concurently(Simultaneously)
*/
public class App {
public static void main(String[] args) {
//Thread Pool
ExecutorService executor = Executors.newFixedThreadPool(2);
for(int i = 0; i < 5; i++){
executor.submit(new Processor( (i+1) )); //Assign task to the Thread(Worker
}
executor.shutdown(); //Will shutdown After the task is Completed
System.out.println("All Task Submitted!");
try {
executor.awaitTermination(1, TimeUnit.DAYS); //Wait for 1 Day then ONLY terminate
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("All Task Completed!");
}//ENDof Main
}
class Processor implements Runnable{
private int id;
public Processor(int id){
this.id = id;
}
@Override
public void run() {
System.out.println("Starting: " + id);
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Completed: " + id);
}
}
OUTPUT
Starting: 1
All Task Submitted!
Starting: 2
Completed: 2
Completed: 1
Starting: 3
Starting: 4
Completed: 4
Completed: 3
Starting: 5
Completed: 5
All Task Completed!
##Lesson5 : CountDown Latches
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/*
* CountDown Latches
* Run Concurently(Simultaneously)
*/
public class App {
public static void main(String[] args) {
//Wait Till the latch reach 0 ==> Then only proceed
CountDownLatch latch = new CountDownLatch(3);
ExecutorService executor = Executors.newFixedThreadPool(3);
for (int i = 0; i < 3 ; i++){
executor.submit(new Processor(latch));
}
try {
latch.await(); //Waits until countDown() reached 0
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("Completed....");
}//ENDof Main
}
class Processor implements Runnable{
private CountDownLatch latch;
public Processor(CountDownLatch latch){
this.latch = latch;
}
@Override
public void run() {
System.out.println("Started...");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
latch.countDown(); //count = count-1
}//ENDof RUN
}
OUTPUT
Started...
Started...
Started...
Completed....
##Lesson6 : Producer Consumer
import java.util.Random;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
/*
* Producer Consumer
* Run Concurently(Simultaneously)
*/
public class App {
//Add/Remvoe item
private static BlockingQueue<Integer> queue = new ArrayBlockingQueue<Integer>(10);
public static void main(String[] args) {
Thread t1 = new Thread(new Runnable(){
@Override
public void run() {
try {
producer();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
Thread t2 = new Thread(new Runnable(){
@Override
public void run() {
try {
consumer();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
//Start it
t1.start();
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}//ENDof Main
private static void producer() throws InterruptedException{
Random random = new Random();
while(true){
queue.put(random.nextInt(100)); //Range from 0-99
}
}//ENDof Producer()
private static void consumer() throws InterruptedException{
Random random = new Random();
while(true){
Thread.sleep(100);
if (random.nextInt(10) == 0){
Integer value = queue.take(); //Retrieve and remove the head value
System.out.println("Taken value: " + value +
"; Queue Size: " + queue.size());
}
}
}//ENDof Consumer()
}
OUTPUT
Taken value: 48; Queue Size: 10
Taken value: 9; Queue Size: 9
Taken value: 83; Queue Size: 10
Taken value: 65; Queue Size: 9
Taken value: 99; Queue Size: 9
Taken value: 5; Queue Size: 10
Taken value: 56; Queue Size: 9
Taken value: 17; Queue Size: 9
Taken value: 3; Queue Size: 9
Taken value: 6; Queue Size: 9
Taken value: 39; Queue Size: 10
Taken value: 43; Queue Size: 9
Taken value: 53; Queue Size: 9
##Lesson7 : Wait & Notify (Low-level Synchronize technique)
wait()
tells the calling thread to give up the monitor and go to sleep until some other thread enters the same monitor and calls notify( ).notify()
wakes up the first thread that calledwait()
on the same object.waity()
andnotify()
can only be called inside thesynchronized
blocks of code.
Processor.java
import java.util.Scanner;
/*
* wait() tells the calling thread to give up the monitor and go to sleep until some other thread enters the same monitor and calls notify( ).
* notify() wakes up the first thread that called wait() on the same object.
*/
public class Processor {
public void produce() throws InterruptedException{
synchronized(this) { //On the Procesor Object
System.out.println("Producer thread running...");
wait(); //Only can be called inside Synchronize block
System.out.println("Resumed...");
}
}//EndOf Produce()
public void consume() throws InterruptedException{
Scanner scanner = new Scanner(System.in);
Thread.sleep(2000);
synchronized(this) { //On the Procesor Object
System.out.println("Waiting for return key...");
scanner.nextLine();
System.out.println("Return key pressed");
notify(); //Notify the wait() object
Thread.sleep(5000);
}
scanner.close();
}//EndOf Consume()
}
App.java
/*
* Wait & Notify
* Run Concurently(Simultaneously)
*/
public class App {
public static void main(String[] args) throws InterruptedException {
final Processor processor = new Processor();
Thread t1 = new Thread(new Runnable(){
@Override
public void run() {
try {
processor.produce();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
Thread t2 = new Thread(new Runnable(){
@Override
public void run() {
try {
processor.consume();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
//Start
t1.start();
t2.start();
t1.join();
t2.join();
}//ENDof Main
}
OUTPUT
Producer thread running...
Waiting for return key...
Return key pressed
Resumed...
##Resources