Skip to content

Instantly share code, notes, and snippets.

@yclim95
Last active November 5, 2023 18:13
Show Gist options
  • Save yclim95/6aa4e8faa7b80f6bff681aa3a36ae596 to your computer and use it in GitHub Desktop.
Save yclim95/6aa4e8faa7b80f6bff681aa3a36ae596 to your computer and use it in GitHub Desktop.
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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment