├── Subtractor.class ├── ThreadPriority.java ├── JoinThreadExample.java ├── ExtendsThreadClass.java ├── PracticeQuestions ├── Print1to10.java ├── ThreadABC.java ├── SumTo100.java ├── OddEven.java └── ProducerConsumer.java ├── ExecutorService ├── CPU_IntensiveTask.java ├── CountSum100.java ├── FixedThreadPoolDemo.java ├── SingleThreadExecutor.java ├── CachedThreadPoolDemo.java ├── ScheduledExecutorDemo.java └── CallableDemo.java ├── RunnableThreadExample.java ├── threadSynchronizationDemo ├── PrintNums1to100.java ├── SynchronizationDemo.java └── LockWithCustomVar.java ├── concurrentCollection ├── SynchronizedCollection.java ├── CountDown.java └── BlockingQueueDemo.java ├── DaemonUser.java ├── WaitAndNotify.java ├── AdderSubtractor.java ├── ProducerConsumer.java ├── PrimeNumberUsingThreads.java └── README.md /Subtractor.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dibyo10/Multithreading_Concurrency_Learning/HEAD/Subtractor.class -------------------------------------------------------------------------------- /ThreadPriority.java: -------------------------------------------------------------------------------- 1 | public class ThreadPriority { 2 | public static void main(String[] args) { 3 | System.out.println(Thread.currentThread().getName()+" says hi!!"); 4 | System.out.println(Thread.currentThread().getPriority()); 5 | 6 | 7 | 8 | 9 | Thread one=new Thread(()->{ 10 | System.out.println("Thread one says hi.."); 11 | System.out.println(Thread.currentThread().getPriority()); 12 | }); 13 | 14 | one.setPriority(Thread.MAX_PRIORITY); 15 | one.start(); 16 | 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /JoinThreadExample.java: -------------------------------------------------------------------------------- 1 | public class JoinThreadExample { 2 | public static void main(String[] args) throws InterruptedException { 3 | Thread one = new Thread(()->{ 4 | for (int i = 0; i < 10; i++) { 5 | System.out.println("Thread 1 : "+i); 6 | 7 | } 8 | }); 9 | Thread two = new Thread(()->{ 10 | for (int i = 0; i < 8; i++) { 11 | System.out.println("Thread 2 : "+i); 12 | 13 | } 14 | }); 15 | 16 | one.start(); 17 | two.start(); 18 | one.join(); 19 | 20 | System.out.println("Done"); 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /ExtendsThreadClass.java: -------------------------------------------------------------------------------- 1 | public class ExtendsThreadClass { 2 | public static void main(String[] args) { 3 | 4 | Thread one=new Thread1(); 5 | Thread two=new Thread2(); 6 | 7 | one.start(); 8 | two.start(); 9 | 10 | } 11 | } 12 | 13 | class Thread1 extends Thread{ 14 | @Override 15 | public void run(){ 16 | for (int i = 0; i <10 ; i++) { 17 | System.out.println("Thread 1 : "+i); 18 | 19 | } 20 | } 21 | } 22 | 23 | class Thread2 extends Thread{ 24 | @Override 25 | public void run(){ 26 | for (int i = 0; i <15 ; i++) { 27 | System.out.println("Thread 2 : "+i); 28 | 29 | } 30 | } 31 | } 32 | 33 | -------------------------------------------------------------------------------- /PracticeQuestions/Print1to10.java: -------------------------------------------------------------------------------- 1 | package PracticeQuestions; 2 | 3 | import java.util.concurrent.ExecutorService; 4 | import java.util.concurrent.Executors; 5 | 6 | public class Print1to10 { 7 | public static void main(String[] args) { 8 | int n=20; 9 | try(ExecutorService ex= Executors.newFixedThreadPool(n)){ 10 | for (int i = 1; i <=n ; i++) { 11 | ex.execute(new Print(i)); 12 | 13 | } 14 | } 15 | } 16 | } 17 | class Print implements Runnable{ 18 | int n; 19 | 20 | Print(int n){ 21 | this.n=n; 22 | } 23 | @Override 24 | public void run(){ 25 | System.out.println(n+" by "+Thread.currentThread().getName()); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /ExecutorService/CPU_IntensiveTask.java: -------------------------------------------------------------------------------- 1 | package ExecutorService; 2 | 3 | import java.util.concurrent.ExecutorService; 4 | import java.util.concurrent.Executors; 5 | 6 | public class CPU_IntensiveTask { 7 | public static void main(String[] args) { 8 | int cores=Runtime.getRuntime().availableProcessors(); 9 | ExecutorService executor= Executors.newFixedThreadPool(cores); 10 | System.out.println("Created thread pool with : "+cores+" cores"); 11 | for (int i = 0; i <20 ; i++) { 12 | executor.execute(new CPUTask()); 13 | 14 | } 15 | } 16 | } 17 | 18 | class CPUTask implements Runnable{ 19 | @Override 20 | public void run(){ 21 | System.out.println("task done by "+Thread.currentThread().getName()); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /RunnableThreadExample.java: -------------------------------------------------------------------------------- 1 | 2 | public class RunnableThreadExample { 3 | public static void main(String[] args) { 4 | 5 | Thread one=new Thread(new ThreadOne()); 6 | Thread two=new Thread(new ThreadTwo()); 7 | Thread three=new Thread(()->{ 8 | for (int i = 0; i < 10; i++) { 9 | System.out.println("Thread 3 : "+i); 10 | 11 | } 12 | }); 13 | one.start(); 14 | two.start(); 15 | three.start(); 16 | System.out.println("Done execution"); 17 | } 18 | } 19 | class ThreadOne implements Runnable{ 20 | @Override 21 | public void run(){ 22 | for(int i=0;i<10;i++){ 23 | System.out.println("Thread 1 : "+i); 24 | } 25 | } 26 | } 27 | 28 | class ThreadTwo implements Runnable{ 29 | @Override 30 | public void run(){ 31 | for(int i=0;i<15;i++){ 32 | System.out.println("Thread 2 : "+i); 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /ExecutorService/CountSum100.java: -------------------------------------------------------------------------------- 1 | package ExecutorService; 2 | 3 | import java.util.concurrent.ExecutorService; 4 | import java.util.concurrent.Executors; 5 | 6 | public class CountSum100 { 7 | public static void main(String[] args) { 8 | int sum=0; 9 | try(ExecutorService executor= Executors.newFixedThreadPool(100)){ 10 | for (int i = 0; i < 100; i++) { 11 | executor.execute(new Adder(sum++)); 12 | 13 | 14 | } 15 | } 16 | System.out.println(sum); 17 | /*for (int i = 0; i <100 ; i++) { 18 | sum++; 19 | 20 | } 21 | System.out.println(sum);*/ 22 | 23 | 24 | } 25 | } 26 | 27 | class Adder implements Runnable{ 28 | int sum=0; 29 | 30 | public Adder(int sum){ 31 | this.sum=sum; 32 | } 33 | @Override 34 | public void run(){ 35 | 36 | System.out.println(Thread.currentThread().getName()+" used"); 37 | 38 | 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /ExecutorService/FixedThreadPoolDemo.java: -------------------------------------------------------------------------------- 1 | package ExecutorService; 2 | 3 | import java.util.concurrent.ExecutorService; 4 | import java.util.concurrent.Executors; 5 | 6 | public class FixedThreadPoolDemo{ 7 | public static void main(String[] args) { 8 | try(ExecutorService executor= Executors.newFixedThreadPool(10)){ 9 | for (int i = 0; i <20 ; i++) { 10 | executor.execute(new Worker(i)); 11 | 12 | 13 | } 14 | 15 | } 16 | 17 | } 18 | 19 | } 20 | 21 | class Worker implements Runnable{ 22 | int taskid; 23 | 24 | public Worker(int taskid){ 25 | this.taskid=taskid; 26 | } 27 | 28 | @Override 29 | public void run(){ 30 | System.out.println("TaskID: "+taskid+" executed by thread "+Thread.currentThread().getName()); 31 | 32 | try{ 33 | Thread.sleep(500); 34 | }catch(InterruptedException e){ 35 | throw new RuntimeException(e); 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /ExecutorService/SingleThreadExecutor.java: -------------------------------------------------------------------------------- 1 | package ExecutorService; 2 | 3 | import java.util.concurrent.ExecutorService; 4 | import java.util.concurrent.Executors; 5 | 6 | public class SingleThreadExecutor { 7 | public static void main(String[] args) { 8 | try(ExecutorService service= Executors.newSingleThreadExecutor()){ 9 | for (int i = 0; i < 5 ; i++) { 10 | service.execute(new Task(i)); 11 | 12 | } 13 | } 14 | } 15 | 16 | 17 | } 18 | 19 | class Task implements Runnable{ 20 | int taskid; 21 | 22 | public Task(int taskid){ 23 | this.taskid=taskid; 24 | } 25 | 26 | @Override 27 | public void run(){ 28 | System.out.println("Task with ID "+taskid+" being executed by thread "+Thread.currentThread().getName()); 29 | try{ 30 | Thread.sleep(500); 31 | }catch(InterruptedException e){ 32 | throw new RuntimeException(e); 33 | 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /ExecutorService/CachedThreadPoolDemo.java: -------------------------------------------------------------------------------- 1 | package ExecutorService; 2 | 3 | import java.util.concurrent.Executor; 4 | import java.util.concurrent.ExecutorService; 5 | import java.util.concurrent.Executors; 6 | 7 | public class CachedThreadPoolDemo { 8 | public static void main(String[] args) { 9 | try(ExecutorService executor=Executors.newCachedThreadPool()){ 10 | for (int i = 0; i < 1000; i++) { 11 | executor.execute(new Work(i)); 12 | 13 | } 14 | } 15 | } 16 | 17 | } 18 | 19 | class Work implements Runnable{ 20 | int taskid; 21 | 22 | public Work(int taskid){ 23 | this.taskid=taskid; 24 | } 25 | 26 | @Override 27 | public void run(){ 28 | System.out.println("Task "+taskid+" executed by "+Thread.currentThread().getName()); 29 | try{ 30 | Thread.sleep(1000); 31 | }catch(InterruptedException e){ 32 | throw new RuntimeException(e); 33 | } 34 | } 35 | 36 | 37 | } 38 | -------------------------------------------------------------------------------- /threadSynchronizationDemo/PrintNums1to100.java: -------------------------------------------------------------------------------- 1 | package threadSynchronizationDemo; 2 | 3 | import java.util.ArrayList; 4 | import java.util.concurrent.ExecutorService; 5 | import java.util.concurrent.Executors; 6 | 7 | public class PrintNums1to100 { 8 | public static void main(String[] args) { 9 | 10 | for(int i=0;i<100;i++){ 11 | Print print = new Print(i); 12 | Thread t=new Thread(print); 13 | t.start(); 14 | try { 15 | t.join(); 16 | } catch (InterruptedException e) { 17 | throw new RuntimeException(e); 18 | } 19 | } 20 | 21 | 22 | 23 | } 24 | 25 | } 26 | 27 | class Print implements Runnable{ 28 | int count=0; 29 | 30 | 31 | public Print(int count){ 32 | this.count=count; 33 | 34 | } 35 | @Override 36 | public synchronized void run(){ 37 | 38 | System.out.println(count+" by "+Thread.currentThread().getName()); 39 | 40 | 41 | 42 | } 43 | 44 | 45 | 46 | } 47 | -------------------------------------------------------------------------------- /threadSynchronizationDemo/SynchronizationDemo.java: -------------------------------------------------------------------------------- 1 | package threadSynchronizationDemo; 2 | 3 | public class SynchronizationDemo { 4 | 5 | private static int count=0; 6 | 7 | public static void main(String[] args) { 8 | 9 | Thread one=new Thread(()->{ 10 | for (int i = 0; i < 50; i++) { 11 | 12 | increment(); 13 | 14 | 15 | } 16 | }); 17 | 18 | Thread two=new Thread(()->{ 19 | for (int i = 0; i < 50; i++) { 20 | 21 | increment(); 22 | 23 | } 24 | }); 25 | 26 | one.start(); 27 | two.start(); 28 | try { 29 | one.join(); 30 | two.join(); 31 | } catch (InterruptedException e) { 32 | throw new RuntimeException(e); 33 | } 34 | 35 | System.out.println(count); 36 | 37 | 38 | 39 | 40 | 41 | } 42 | private synchronized static void increment(){ 43 | count++; 44 | } //synchronized prevents resource sharing 45 | 46 | } 47 | -------------------------------------------------------------------------------- /PracticeQuestions/ThreadABC.java: -------------------------------------------------------------------------------- 1 | package PracticeQuestions; 2 | 3 | public class ThreadABC { 4 | public static void main(String[] args) { 5 | Thread one=new Thread(()->{ 6 | System.out.println("one done"); 7 | }); 8 | Thread two=new Thread(()->{ 9 | System.out.println("two done"); 10 | }); 11 | Thread three=new Thread(()->{ 12 | System.out.println("three done"); 13 | }); 14 | 15 | 16 | 17 | try { 18 | one.start(); 19 | one.join(); 20 | 21 | } catch (InterruptedException e) { 22 | throw new RuntimeException(e); 23 | } 24 | 25 | try { 26 | two.start(); 27 | two.join(); 28 | } catch (InterruptedException e) { 29 | throw new RuntimeException(e); 30 | } 31 | try { 32 | three.start(); 33 | three.join(); 34 | } catch (InterruptedException e) { 35 | throw new RuntimeException(e); 36 | } 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /concurrentCollection/SynchronizedCollection.java: -------------------------------------------------------------------------------- 1 | package concurrentCollection; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Collections; 5 | import java.util.List; 6 | 7 | public class SynchronizedCollection { 8 | 9 | public static void main(String[] args) { 10 | List list= Collections.synchronizedList(new ArrayList<>()); 11 | 12 | final Object lock=new Object(); 13 | 14 | Thread one=new Thread(()->{ 15 | for (int i = 0; i < 1000; i++) { 16 | 17 | list.add(i); 18 | 19 | 20 | 21 | } 22 | }); 23 | Thread two=new Thread(()->{ 24 | for (int i = 0; i < 1000; i++) { 25 | 26 | list.add(i); 27 | 28 | 29 | } 30 | }); 31 | one.start(); 32 | two.start(); 33 | 34 | try { 35 | one.join(); 36 | two.join(); 37 | } catch (InterruptedException e) { 38 | throw new RuntimeException(e); 39 | } 40 | System.out.println(list.size()); 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /DaemonUser.java: -------------------------------------------------------------------------------- 1 | public class DaemonUser { 2 | public static void main(String[] args) { 3 | 4 | Thread daemon=new Thread(new Daemon()); 5 | Thread user=new Thread(new User()); 6 | 7 | daemon.setDaemon(true); 8 | 9 | daemon.start(); 10 | user.start(); 11 | 12 | } 13 | } 14 | class Daemon implements Runnable{ 15 | @Override 16 | public void run(){ 17 | int count=0; 18 | while(count<500){ 19 | try { 20 | Thread.sleep(1000); 21 | } catch (InterruptedException e) { 22 | throw new RuntimeException(e); 23 | } 24 | count++; 25 | System.out.println("Daemon running.."); 26 | } 27 | 28 | } 29 | } 30 | 31 | class User implements Runnable{ 32 | @Override 33 | public void run(){ 34 | try { 35 | Thread.sleep(5000); 36 | } catch (InterruptedException e) { 37 | throw new RuntimeException(e); 38 | } 39 | System.out.println("User thread done"); 40 | 41 | 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /ExecutorService/ScheduledExecutorDemo.java: -------------------------------------------------------------------------------- 1 | package ExecutorService; 2 | 3 | import java.util.concurrent.Executors; 4 | import java.util.concurrent.ScheduledExecutorService; 5 | import java.util.concurrent.TimeUnit; 6 | 7 | public class ScheduledExecutorDemo { 8 | public static void main(String[] args) { 9 | ScheduledExecutorService executor= Executors.newScheduledThreadPool(2); 10 | executor.scheduleAtFixedRate(new ProbeTask(),1000,2000, TimeUnit.MILLISECONDS); 11 | executor.scheduleAtFixedRate(new AnotherOne(),1000,2000, TimeUnit.MILLISECONDS); 12 | 13 | try{ 14 | if(!executor.awaitTermination(10000,TimeUnit.MILLISECONDS)){ 15 | executor.shutdownNow(); 16 | } 17 | }catch(InterruptedException e){ 18 | executor.shutdownNow(); 19 | 20 | } 21 | } 22 | } 23 | 24 | class ProbeTask implements Runnable{ 25 | @Override 26 | public void run(){ 27 | System.out.println("probing1.. with "+Thread.currentThread().getName()); 28 | } 29 | } 30 | 31 | class AnotherOne implements Runnable{ 32 | @Override 33 | public void run(){ 34 | System.out.println("probing2.. with "+Thread.currentThread().getName()); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /WaitAndNotify.java: -------------------------------------------------------------------------------- 1 | public class WaitAndNotify { 2 | 3 | private static final Object lock=new Object(); 4 | 5 | 6 | public static void main(String[] args) { 7 | Thread t1=new Thread(()->{ 8 | try { 9 | one(); 10 | } catch (InterruptedException e) { 11 | throw new RuntimeException(e); 12 | } 13 | 14 | }); 15 | 16 | Thread t2=new Thread(()->{ 17 | try { 18 | two(); 19 | } catch (InterruptedException e) { 20 | throw new RuntimeException(e); 21 | } 22 | 23 | }); 24 | 25 | t1.start(); 26 | t2.start(); 27 | } 28 | private static void one() throws InterruptedException{ 29 | synchronized (lock){ 30 | System.out.println("Method 1 says hello"); 31 | lock.wait(); 32 | System.out.println("Back again in method one"); 33 | } 34 | } 35 | 36 | private static void two() throws InterruptedException{ 37 | synchronized (lock){ 38 | System.out.println("Method 2 says hello"); 39 | lock.notify(); 40 | System.out.println("Hello from method two even after notifying"); 41 | } 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /ExecutorService/CallableDemo.java: -------------------------------------------------------------------------------- 1 | package ExecutorService; 2 | 3 | import java.util.concurrent.*; 4 | 5 | public class CallableDemo { 6 | public static void main(String[] args) throws InterruptedException, ExecutionException, TimeoutException { 7 | try(ExecutorService executor= Executors.newCachedThreadPool()){ 8 | for (int i = 0; i < 100 ; i++) { 9 | Future res=executor.submit(new Number(i)); 10 | 11 | String ans=res.get(); 12 | 13 | if(!ans.isEmpty()){ 14 | System.out.println(ans); 15 | } 16 | 17 | } 18 | } 19 | 20 | } 21 | } 22 | 23 | class Number implements Callable{ 24 | int n; 25 | 26 | Number(int n){ 27 | this.n=n; 28 | } 29 | @Override 30 | public String call() throws Exception{ 31 | 32 | if(isPrime(n)){ 33 | return (n+" is Prime by "+Thread.currentThread().getName()); 34 | }else{ 35 | return(""); 36 | } 37 | } 38 | 39 | public boolean isPrime(int n){ 40 | if (n <= 1) return false; 41 | for (int i = 2; i <= Math.sqrt(n); i++) { 42 | if (n % i == 0) return false; 43 | } 44 | return true; 45 | 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /AdderSubtractor.java: -------------------------------------------------------------------------------- 1 | import java.util.concurrent.CountDownLatch; 2 | import java.util.concurrent.ExecutorService; 3 | import java.util.concurrent.Executors; 4 | 5 | public class AdderSubtractor { 6 | public static void main(String[] args) { 7 | int count=0; 8 | final Object lock=new Object(); 9 | try(ExecutorService exe= Executors.newFixedThreadPool(2)){ 10 | for (int i = 0; i < 100; i++) { 11 | synchronized (lock){ 12 | exe.execute(new Adder(count++)); 13 | } 14 | synchronized (lock){ 15 | exe.execute(new Subtractor(count--)); 16 | } 17 | } 18 | 19 | } 20 | 21 | System.out.println(count); 22 | System.out.println("Process done.."); 23 | 24 | } 25 | 26 | } 27 | 28 | class Adder implements Runnable{ 29 | int n; 30 | 31 | public Adder(int n){ 32 | this.n=n; 33 | } 34 | @Override 35 | public void run(){ 36 | n++; 37 | System.out.println("Value incremented to "+n); 38 | 39 | } 40 | } 41 | 42 | class Subtractor implements Runnable{ 43 | int sub; 44 | 45 | 46 | public Subtractor(int sub){ 47 | this.sub=sub; 48 | } 49 | 50 | @Override 51 | public void run(){ 52 | sub--; 53 | System.out.println("Value decremented to "+sub); 54 | 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /threadSynchronizationDemo/LockWithCustomVar.java: -------------------------------------------------------------------------------- 1 | package threadSynchronizationDemo; 2 | 3 | public class LockWithCustomVar { 4 | 5 | private static int counter1=0; 6 | private static int counter2=0; 7 | 8 | private static final Object lock1=new Object(); 9 | private static final Object lock2=new Object(); 10 | 11 | public static void main(String[] args) { 12 | Thread one = new Thread(()->{ 13 | for (int i = 0; i < 10; i++) { 14 | increment1(); 15 | } 16 | }); 17 | 18 | Thread two = new Thread(()->{ 19 | for (int i = 0; i < 10; i++) { 20 | increment2(); 21 | } 22 | }); 23 | 24 | one.start(); 25 | 26 | two.start(); 27 | 28 | 29 | try { 30 | one.join(); 31 | two.join(); 32 | } catch (InterruptedException e) { 33 | throw new RuntimeException(e); 34 | } 35 | System.out.println(counter1 +" == "+counter2); 36 | } 37 | 38 | private static void increment1(){ 39 | synchronized (lock1){ 40 | counter1++; 41 | System.out.println("Incremented counter1 to "+counter1+" using "+Thread.currentThread().getName()); 42 | } 43 | } 44 | private static void increment2(){ 45 | synchronized (lock2){ 46 | counter2++; 47 | System.out.println("Incremented counter2 to "+counter2+" using "+Thread.currentThread().getName()); 48 | } 49 | } 50 | 51 | 52 | } 53 | -------------------------------------------------------------------------------- /concurrentCollection/CountDown.java: -------------------------------------------------------------------------------- 1 | package concurrentCollection; 2 | import java.util.concurrent.CountDownLatch; 3 | import java.util.concurrent.ExecutorService; 4 | import java.util.concurrent.Executors; 5 | 6 | public class CountDown { 7 | public static void main(String[] args) throws InterruptedException { 8 | 9 | int chefs=10; 10 | 11 | CountDownLatch latch=new CountDownLatch(chefs); 12 | 13 | try(ExecutorService ex= Executors.newFixedThreadPool(chefs)){ 14 | for (int i = 0; i < 10; i++) { 15 | ex.execute(new Chef("Dibyo","Pizza",latch)); 16 | Thread.sleep(1000); 17 | 18 | 19 | } 20 | } 21 | latch.await(); 22 | 23 | System.out.println("All dishes ready.."); 24 | 25 | } 26 | } 27 | 28 | class Chef implements Runnable{ 29 | private final String name; 30 | private final String dish; 31 | private final CountDownLatch latch; 32 | 33 | public Chef(String name, String dish, CountDownLatch latch){ 34 | this.dish=dish; 35 | this.name=name; 36 | this.latch=latch; 37 | 38 | } 39 | @Override 40 | public void run(){ 41 | 42 | try{ 43 | System.out.println(name+" is preparing "+dish+" by "+Thread.currentThread().getName()); 44 | Thread.sleep(2000); 45 | System.out.println(name+" has finished preparing "+dish+" by "+Thread.currentThread().getName()); 46 | latch.countDown(); 47 | }catch(InterruptedException e){ 48 | throw new RuntimeException(e); 49 | } 50 | 51 | } 52 | } 53 | 54 | -------------------------------------------------------------------------------- /PracticeQuestions/SumTo100.java: -------------------------------------------------------------------------------- 1 | package PracticeQuestions; 2 | 3 | public class SumTo100 { 4 | static int count=0; 5 | static final Object lock=new Object(); 6 | 7 | public static void main(String[] args) throws InterruptedException { 8 | Thread t1=new Thread(()->{ 9 | synchronized (lock){ 10 | for (int i = 0; i < 1000 ; i++) { 11 | count++; 12 | 13 | } 14 | } 15 | 16 | }); 17 | Thread t2=new Thread(()->{ 18 | synchronized (lock){ 19 | for (int i = 0; i < 1000 ; i++) { 20 | count++; 21 | 22 | } 23 | } 24 | 25 | }); 26 | Thread t3=new Thread(()->{ 27 | synchronized (lock){ 28 | for (int i = 0; i < 1000 ; i++) { 29 | count++; 30 | 31 | } 32 | } 33 | 34 | }); 35 | Thread t4=new Thread(()->{ 36 | synchronized (lock){ 37 | for (int i = 0; i < 1000 ; i++) { 38 | count++; 39 | 40 | } 41 | } 42 | 43 | }); 44 | Thread t5=new Thread(()->{ 45 | synchronized (lock){ 46 | for (int i = 0; i < 1000 ; i++) { 47 | count++; 48 | 49 | } 50 | } 51 | 52 | }); 53 | t1.start(); 54 | t1.join(); 55 | t2.start(); 56 | t2.join(); 57 | t3.start(); 58 | t3.join(); 59 | t4.start(); 60 | t4.join(); 61 | t5.start(); 62 | t5.join(); 63 | 64 | System.out.println(count); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /ProducerConsumer.java: -------------------------------------------------------------------------------- 1 | import java.util.ArrayList; 2 | import java.util.concurrent.ArrayBlockingQueue; 3 | import java.util.concurrent.BlockingQueue; 4 | 5 | public class ProducerConsumer { 6 | public static void main(String[] args) { 7 | BlockingQueue queue=new ArrayBlockingQueue<>(5); 8 | Thread p1=new Thread(new Producer(queue)); 9 | Thread p2=new Thread(new Producer(queue)); 10 | Thread c1=new Thread(new Consumer(queue)); 11 | Thread c2=new Thread(new Consumer(queue)); 12 | 13 | 14 | p1.start(); 15 | p2.start(); 16 | c1.start(); 17 | c2.start(); 18 | 19 | 20 | } 21 | 22 | 23 | } 24 | 25 | class Producer implements Runnable{ 26 | private BlockingQueue queue; 27 | 28 | Producer(BlockingQueue queue) { 29 | this.queue = queue; 30 | } 31 | 32 | @Override 33 | public void run(){ 34 | while (true){ 35 | try{ 36 | queue.put("Product"); 37 | System.out.println("Produced by " + Thread.currentThread().getName()); 38 | Thread.sleep(1000); 39 | }catch(InterruptedException e){ 40 | throw new RuntimeException(e); 41 | } 42 | } 43 | 44 | } 45 | 46 | } 47 | 48 | class Consumer implements Runnable{ 49 | private BlockingQueue queue; 50 | 51 | Consumer(BlockingQueue queue) { 52 | this.queue = queue; 53 | } 54 | 55 | @Override 56 | public void run(){ 57 | while(true){ 58 | try{ 59 | String product = queue.take(); 60 | System.out.println("Consumed by " + Thread.currentThread().getName()); 61 | Thread.sleep(1200); 62 | }catch(InterruptedException e){ 63 | throw new RuntimeException(e); 64 | } 65 | 66 | } 67 | 68 | } 69 | 70 | } -------------------------------------------------------------------------------- /PracticeQuestions/OddEven.java: -------------------------------------------------------------------------------- 1 | package PracticeQuestions; 2 | 3 | public class OddEven { 4 | public static void main(String[] args) { 5 | SharedPrinter printer = new SharedPrinter(1, 30); // print 1 to 30 6 | 7 | Thread oddThread = new Thread(() -> { 8 | try { 9 | printer.printOdd(); 10 | } catch (InterruptedException e) { 11 | e.printStackTrace(); 12 | } 13 | }); 14 | 15 | Thread evenThread = new Thread(() -> { 16 | try { 17 | printer.printEven(); 18 | } catch (InterruptedException e) { 19 | e.printStackTrace(); 20 | } 21 | }); 22 | 23 | oddThread.start(); 24 | evenThread.start(); 25 | } 26 | } 27 | 28 | class SharedPrinter { 29 | private int number; 30 | private final int max; 31 | private final Object lock = new Object(); 32 | 33 | public SharedPrinter(int start, int max) { 34 | this.number = start; 35 | this.max = max; 36 | } 37 | 38 | public void printOdd() throws InterruptedException { 39 | while (number <= max) { 40 | synchronized (lock) { 41 | if (number % 2 == 0) { 42 | lock.wait(); 43 | } else { 44 | System.out.println("Odd: " + number + " by " + Thread.currentThread().getName()); 45 | number++; 46 | lock.notify(); 47 | } 48 | } 49 | } 50 | } 51 | 52 | public void printEven() throws InterruptedException { 53 | while (number <= max) { 54 | synchronized (lock) { 55 | if (number % 2 != 0) { 56 | lock.wait(); 57 | } else { 58 | System.out.println("Even: " + number + " by " + Thread.currentThread().getName()); 59 | number++; 60 | lock.notify(); 61 | } 62 | } 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /PrimeNumberUsingThreads.java: -------------------------------------------------------------------------------- 1 | import java.util.Scanner; 2 | 3 | public class PrimeNumberUsingThreads { 4 | public static void main(String[] args) { 5 | Scanner sc = new Scanner(System.in); 6 | System.out.print("Enter upper limit (n): "); 7 | int n = sc.nextInt(); 8 | System.out.print("Enter number of threads: "); 9 | int noOfThreads = sc.nextInt(); 10 | 11 | Thread[] threads = new Thread[noOfThreads]; 12 | 13 | int rangeSize = n / noOfThreads; 14 | int remainder = n % noOfThreads; 15 | 16 | int start = 1; 17 | 18 | for (int i = 0; i < noOfThreads; i++) { 19 | int end = start + rangeSize - 1; 20 | 21 | 22 | if (i == noOfThreads - 1) { 23 | end = n; 24 | } 25 | 26 | Check task = new Check(start, end); 27 | threads[i] = new Thread(task); 28 | threads[i].start(); 29 | 30 | start = end + 1; 31 | } 32 | 33 | for (int i = 0; i < noOfThreads; i++) { 34 | try { 35 | threads[i].join(); 36 | } catch (InterruptedException e) { 37 | throw new RuntimeException(e); 38 | } 39 | } 40 | 41 | System.out.println("All threads finished."); 42 | } 43 | } 44 | 45 | class Check implements Runnable { 46 | private int start, end; 47 | 48 | public Check(int start, int end) { 49 | this.start = start; 50 | this.end = end; 51 | } 52 | 53 | @Override 54 | public void run() { 55 | for (int i = start; i <= end; i++) { 56 | if (isPrime(i)) { 57 | System.out.println(i + " is prime (checked by " + Thread.currentThread().getName() + ")"); 58 | } 59 | } 60 | } 61 | 62 | private boolean isPrime(int n) { 63 | if (n <= 1) return false; 64 | if (n == 2) return true; 65 | if (n % 2 == 0) return false; 66 | 67 | for (int i = 3; i * i <= n; i += 2) { 68 | if (n % i == 0) return false; 69 | } 70 | 71 | return true; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /concurrentCollection/BlockingQueueDemo.java: -------------------------------------------------------------------------------- 1 | package concurrentCollection; 2 | import java.util.concurrent.atomic.AtomicInteger; 3 | import java.util.concurrent.ArrayBlockingQueue; 4 | import java.util.concurrent.BlockingQueue; 5 | import java.util.concurrent.ExecutorService; 6 | import java.util.concurrent.Executors; 7 | 8 | public class BlockingQueueDemo { 9 | static final int capacity = 5; 10 | static BlockingQueue queue=new ArrayBlockingQueue<>(capacity); 11 | 12 | public static void main(String[] args) { 13 | 14 | try(ExecutorService ex= Executors.newFixedThreadPool(5)){ 15 | Producer producer=new Producer(queue); 16 | Consumer consumer=new Consumer(queue); 17 | ex.execute(producer); 18 | ex.execute(producer); 19 | ex.execute(producer); 20 | ex.execute(consumer); 21 | ex.execute(consumer); 22 | ex.execute(consumer); 23 | 24 | } 25 | 26 | 27 | } 28 | } 29 | 30 | class Producer implements Runnable { 31 | private BlockingQueue queue; 32 | 33 | // Shared static counter for all producers 34 | private static final AtomicInteger counter = new AtomicInteger(); 35 | 36 | Producer(BlockingQueue queue) { 37 | this.queue = queue; 38 | } 39 | 40 | @Override 41 | public void run() { 42 | while (true) { 43 | try { 44 | int product = counter.getAndIncrement(); // Get a unique number 45 | queue.put(product); 46 | System.out.println("Produced: " + product + " by " + Thread.currentThread().getName() + " Queue Size: " + queue.size()); 47 | 48 | Thread.sleep(500); 49 | } catch (InterruptedException e) { 50 | Thread.currentThread().interrupt(); // good practice 51 | // optionally exit the loop 52 | } 53 | } 54 | } 55 | } 56 | 57 | class Consumer implements Runnable{ 58 | private BlockingQueue queue; 59 | Consumer(BlockingQueue queue) { 60 | this.queue = queue; 61 | } 62 | @Override 63 | public void run(){ 64 | 65 | while (true){ 66 | try{ 67 | queue.take(); 68 | System.out.println("Consumed: " + "by " + Thread.currentThread().getName()+" Queue Size: " + queue.size()); 69 | 70 | 71 | }catch (InterruptedException e){ 72 | throw new RuntimeException(e); 73 | } 74 | try { 75 | Thread.sleep(1500); 76 | } catch (InterruptedException e) { 77 | throw new RuntimeException(e); 78 | } 79 | 80 | } 81 | } 82 | 83 | 84 | } 85 | -------------------------------------------------------------------------------- /PracticeQuestions/ProducerConsumer.java: -------------------------------------------------------------------------------- 1 | package PracticeQuestions; 2 | 3 | import java.util.ArrayList; 4 | import java.util.concurrent.ExecutorService; 5 | import java.util.concurrent.Executors; 6 | 7 | public class ProducerConsumer { 8 | public static void main(String[] args) { 9 | ArrayList products=new ArrayList<>(); 10 | for(int i=0;i<10;i++){ 11 | products.add("Product"); 12 | } 13 | ProduceConsume task=new ProduceConsume(10,products); 14 | ExecutorService ex=Executors.newCachedThreadPool(); 15 | 16 | ex.submit(()->{ 17 | try{ 18 | task.produce(); 19 | } catch (InterruptedException e) { 20 | throw new RuntimeException(e); 21 | } 22 | }); 23 | 24 | ex.submit(()->{ 25 | try{ 26 | task.produce(); 27 | } catch (InterruptedException e) { 28 | throw new RuntimeException(e); 29 | } 30 | }); 31 | 32 | ex.submit(()->{ 33 | try{ 34 | task.consume(); 35 | } catch (InterruptedException e) { 36 | throw new RuntimeException(e); 37 | } 38 | }); 39 | 40 | ex.submit(()->{ 41 | try{ 42 | task.consume(); 43 | } catch (InterruptedException e) { 44 | throw new RuntimeException(e); 45 | } 46 | }); 47 | 48 | 49 | 50 | } 51 | } 52 | class ProduceConsume{ 53 | ArrayList products; 54 | int max; 55 | int count; 56 | final Object lock=new Object(); 57 | 58 | ProduceConsume(int max,ArrayList products){ 59 | this.products=products; 60 | this.max=max; 61 | 62 | } 63 | public void produce() throws InterruptedException { 64 | while(true){ 65 | synchronized (lock){ 66 | if(products.size()==max){ 67 | System.out.println("Container full..waiting to be consumed"); 68 | try { 69 | 70 | lock.wait(); 71 | } catch (InterruptedException e) { 72 | throw new RuntimeException(e); 73 | } 74 | }else{ 75 | products.add("Product"); 76 | System.out.println("Another Product produced.. and current size "+products.size()+" by "+Thread.currentThread().getName()); 77 | lock.notifyAll(); 78 | 79 | 80 | } 81 | } 82 | Thread.sleep(1000); 83 | 84 | } 85 | 86 | } 87 | public void consume() throws InterruptedException { 88 | while(true){ 89 | synchronized (lock){ 90 | if(products.size()==0){ 91 | System.out.println("Container empty..waiting to be produced by "+Thread.currentThread().getName()); 92 | try { 93 | 94 | lock.wait(); 95 | } catch (InterruptedException e) { 96 | throw new RuntimeException(e); 97 | } 98 | }else{ 99 | products.removeFirst(); 100 | System.out.println("Another Product consumed.. and current size "+products.size()+" by "+Thread.currentThread().getName()); 101 | lock.notifyAll(); 102 | 103 | 104 | } 105 | } 106 | Thread.sleep(1000); 107 | } 108 | } 109 | 110 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Multithreading & Concurrency Learning in Java 2 | 3 |

4 | Java Logo 5 |

6 | 7 |

8 | All my learnings, notes, and implementations around Multithreading & Concurrency in Java 🚀 9 |

10 | 11 | --- 12 | 13 | ## 📚 About This Repository 14 | 15 | This repository is a comprehensive collection of my explorations and hands-on implementations of **multithreading** and **concurrency** concepts in Java. It includes code samples, theoretical notes, best practices, common pitfalls, and advanced topics. 16 | 17 | Whether you are a beginner or brushing up on concurrency, you'll find practical examples and explanations here! 18 | 19 | --- 20 | 21 | ## Table of Contents 22 | 23 | 1. [Core Multithreading Concepts](#core-multithreading-concepts) 24 | 2. [Executor Service](#executor-service) 25 | 3. [Practice Questions](#practice-questions) 26 | 4. [Concurrent Collections](#concurrent-collections) 27 | 5. [Thread Synchronization Demos](#thread-synchronization-demos) 28 | 6. [Build & Run Instructions](#build--run-instructions) 29 | 7. [Contributing & License](#contributing--license) 30 | 31 | --- 32 | 33 | ## Core Multithreading Concepts 34 | 35 | Explore the fundamental building blocks of multithreading in Java, including thread creation, coordination, computation, and thread properties. 36 | 37 | - **Creating Threads** 38 | - [`ExtendsThreadClass.java`](./ExtendsThreadClass.java): Creating threads by extending the `Thread` class. 39 | - [`RunnableThreadExample.java`](./RunnableThreadExample.java): Implementing threads using the `Runnable` interface. 40 | - **Thread Coordination** 41 | - [`JoinThreadExample.java`](./JoinThreadExample.java): Using `join()` for thread coordination. 42 | - [`WaitAndNotify.java`](./WaitAndNotify.java): Inter-thread communication using `wait()` and `notify()`. 43 | - [`ProducerConsumer.java`](./ProducerConsumer.java): Classic producer-consumer problem demo. 44 | - **Thread Priorities & Daemon Threads** 45 | - [`ThreadPriority.java`](./ThreadPriority.java): Working with thread priorities. 46 | - [`DaemonUser.java`](./DaemonUser.java): Demonstrating daemon threads. 47 | - **Computation with Threads** 48 | - [`AdderSubtractor.java`](./AdderSubtractor.java): Performing arithmetic with threads. 49 | - [`PrimeNumberUsingThreads.java`](./PrimeNumberUsingThreads.java): Calculating primes using threads. 50 | 51 | --- 52 | 53 | ## Executor Service 54 | 55 | Learn how to manage thread pools and advanced asynchronous tasks using Java's ExecutorService framework. 56 | 57 | - [`FixedThreadPoolDemo.java`](./ExecutorService/FixedThreadPoolDemo.java): Using a fixed thread pool. 58 | - [`CachedThreadPoolDemo.java`](./ExecutorService/CachedThreadPoolDemo.java): Using a cached thread pool. 59 | - [`SingleThreadExecutor.java`](./ExecutorService/SingleThreadExecutor.java): Single-threaded executor. 60 | - [`ScheduledExecutorDemo.java`](./ExecutorService/ScheduledExecutorDemo.java): Scheduling tasks. 61 | - [`CallableDemo.java`](./ExecutorService/CallableDemo.java): Using Callable and Future for async computation. 62 | - [`CPU_IntensiveTask.java`](./ExecutorService/CPU_IntensiveTask.java): Handling CPU-intensive tasks. 63 | - [`CountSum100.java`](./ExecutorService/CountSum100.java): Summation tasks with thread pools. 64 | 65 | [Browse all ExecutorService examples »](https://github.com/Dibyo10/Multithreading_Concurrency_Learning/tree/main/ExecutorService) 66 | 67 | --- 68 | 69 | ## Practice Questions 70 | 71 | Sharpen your skills with hands-on problems and coding exercises related to thread communication and synchronization. 72 | 73 | - [`OddEven.java`](./PracticeQuestions/OddEven.java): Odd/even number threading problem. 74 | - [`Print1to10.java`](./PracticeQuestions/Print1to10.java): Printing numbers with threads. 75 | - [`ProducerConsumer.java`](./PracticeQuestions/ProducerConsumer.java): Producer-consumer exercise. 76 | - [`SumTo100.java`](./PracticeQuestions/SumTo100.java): Summing numbers using threads. 77 | - [`ThreadABC.java`](./PracticeQuestions/ThreadABC.java): Ordered execution of threads A, B, C. 78 | 79 | [See more practice problems »](https://github.com/Dibyo10/Multithreading_Concurrency_Learning/tree/main/PracticeQuestions) 80 | 81 | --- 82 | 83 | ## Concurrent Collections 84 | 85 | Discover how to use thread-safe collections and synchronization mechanisms for managing shared resources. 86 | 87 | - [`BlockingQueueDemo.java`](./concurrentCollection/BlockingQueueDemo.java): Using `BlockingQueue` for producer-consumer scenarios. 88 | - [`CountDown.java`](./concurrentCollection/CountDown.java): Synchronization with CountDownLatch/related constructs. 89 | - [`SynchronizedCollection.java`](./concurrentCollection/SynchronizedCollection.java): Using synchronized collections in Java. 90 | 91 | [All concurrent collection demos »](https://github.com/Dibyo10/Multithreading_Concurrency_Learning/tree/main/concurrentCollection) 92 | 93 | --- 94 | 95 | ## Thread Synchronization Demos 96 | 97 | Explore different synchronization techniques and locking mechanisms. 98 | 99 | - [`LockWithCustomVar.java`](./threadSynchronizationDemo/LockWithCustomVar.java): Custom lock implementation. 100 | - [`PrintNums1to100.java`](./threadSynchronizationDemo/PrintNums1to100.java): Synchronized number printing. 101 | - [`SynchronizationDemo.java`](./threadSynchronizationDemo/SynchronizationDemo.java): Demonstration of basic synchronization. 102 | 103 | [Browse thread synchronization demos »](https://github.com/Dibyo10/Multithreading_Concurrency_Learning/tree/main/threadSynchronizationDemo) 104 | 105 | --- 106 | 107 | ## 🚦 Getting Started 108 | 109 | To browse or run the code examples: 110 | 1. **Clone this repository:** 111 | ```bash 112 | git clone https://github.com/Dibyo10/Multithreading_Concurrency_Learning.git 113 | ``` 114 | 2. **Open in your favorite Java IDE** (IntelliJ IDEA, Eclipse, VSCode, etc.). 115 | 3. **Run the example files** as standard Java applications. 116 | 117 | --- 118 | ## ▶️ How to Run 119 | 120 | - Each directory contains self-contained Java files with a `main` method. 121 | - Compile and run with: 122 | ```bash 123 | javac path/to/File.java 124 | java path.to.File 125 | ``` 126 | - Or run directly from your IDE. 127 | 128 | --- 129 | 130 | ## 🌟 Useful Resources 131 | 132 | - [Official Java Concurrency Documentation](https://docs.oracle.com/javase/tutorial/essential/concurrency/) 133 | - [Java Concurrency in Practice](https://jcip.net/) 134 | - [Baeldung - Guide to Java Concurrency](https://www.baeldung.com/java-concurrency) 135 | 136 | --- 137 | 138 | ## 🤝 Contributing 139 | 140 | Contributions, suggestions, and doubts are welcome! 141 | Feel free to open issues or pull requests. 142 | 143 | --- 144 | 145 | 146 | 147 |

148 | 149 | 150 |

151 | --------------------------------------------------------------------------------