hatefpalizgar
5/14/2019 - 11:53 PM

Java Multi-Threading Part II

Java Multi-Threading Part II

#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)

  1. 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( ).
  2. notify() wakes up the first thread that called wait() on the same object.
  3. waity() and notify() can only be called inside the synchronized 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

  1. Click Here to Java MultiThreading Part III
  2. Back to JAVA MultiThreading Part I
  3. Main Contents