Multi Threading , concurency

 Threadpool Example

Worker thread:

package com.vasanth.java.concurrent;
public class Workerthread implements Runnable{
private String message;
public Workerthread(String message) {
super();
this.message = message;
}
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+" : Start -> Message="+message);
process();
System.out.println(Thread.currentThread().getName()+": End");

}

private void process() {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}

}


Thread pool:

package com.vasanth.java.concurrent;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class TestThreadPool {
public static void main(String args[]) {
ExecutorService executor = Executors.newFixedThreadPool(5);
for(int i=1;i<10;i++) {
Workerthread workerthread = new Workerthread(""+i);
executor.execute(workerthread);
}
executor.shutdown();
while (!executor.isTerminated()) {   }  
System.out.println("Finished thread execution");
}

}

Producer-Consumer Problem in Multi-threading


This problem can be implemented or solved in different ways in Java, 

The classical way is using the wait & notify method to communicate between Producer and Consumer thread and blocking each of them on individual condition like full queue and empty queue. 

With the introduction of BlockingQueue Data Structure in Java 5 It's now much simpler because BlockingQueue provides this control implicitly by introducing blocking methods put() and take().

Now you don't require to use wait and notify to communicate between Producer and Consumer. BlockingQueue put() method will block if Queue is full in case of Bounded Queue and take() will block if Queue is empty.

BlockingQuue is an interface and Java 5 provides different implantation like ArrayBlockingQueue and LinkedBlockingQueue , both implement FIFO order or elements, while ArrayLinkedQueue is bounded in nature LinkedBlockingQueue is optionally bounded.

Example:

package com.vasanth.Threads;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

public class ProducerConsumer {

public static void main (String args[]){

BlockingQueue queue=new LinkedBlockingQueue(); // You can give fixed size here

Thread producer=new Thread(new Producer(queue));
Thread consumer =new Thread(new Consumer(queue));

producer.start();
consumer.start();
}

}

class Producer implements Runnable{

private final BlockingQueue queue;

public Producer(BlockingQueue queue) {
this.queue=queue;
}

@Override
public void run() {

for (int i=1;i<=10;i++){
try {
System.out.println("Produced:"+i);
queue.put(i);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

class Consumer implements Runnable{

private final BlockingQueue queue;
public Consumer(BlockingQueue queue){
this.queue=queue;
}
@Override
public void run() {
while(true) {
try {
System.out.println("Consume : " + queue.take());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}


ScheduledThreadPoolExecutor Class in Java
This class is useful when we want to schedule tasks to run repeatedly or to run after a given delay for some future time.  It creates a fixed-sized Thread Pool. So when it is initiated, it needs to be given the corePoolSize.
ScheduledThreadPoolExecutor threadPool = (ScheduledThreadPoolExecutor)Executors.newScheduledThreadPool(5);
We can use Executors.newScheduledThreadPool(int corePoolSize) factory method defined by Executors class. It returns a ScheduledExecutorService object which can be type-casted to ScheduledThreadPoolExecutor object.

  • fixedRate : run the task on periodic intervals even if the last invocation may still be running.
  • fixedDelay : specifically controls the next execution time when the last execution finishes.
Example:
package com.vasanth.concurrency;

import java.util.Date;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class Scheduler {
private static int CORE_POOL_SIZE=5;
ScheduledExecutorService threadPool;

public static void main (String args[]){

Scheduler obj=new Scheduler();

//Schedule once after 1 min delay
obj.schedule("task-1",1);

//Schedule recurrence 1 min delay
obj.scheduleWithDelay("task-2",1);

//Schedule recurrence 1 min delay - fixed rate
obj.scheduleWithFixedRate("task-3",1);
}

public void schedule(String name, int interval){
if(threadPool==null){
threadPool=new ScheduledThreadPoolExecutor(CORE_POOL_SIZE);
}
threadPool.schedule(new Task(name),interval,TimeUnit.MINUTES);
}

//Fixed Delay
public void scheduleWithDelay(String name, int interval){
threadPool.scheduleWithFixedDelay(new Task(name),0,interval,TimeUnit.MINUTES);
}

//Fixed Rate
public void scheduleWithFixedRate(String name, int interval){
threadPool.scheduleAtFixedRate(new Task(name),0,interval,TimeUnit.MINUTES);
}
}

class Task implements Runnable{
String name;
public Task(String name){
this.name=name;
}
@Override
public void run() {
System.out.println(new Date()+" Executing "+this.name);
}
}

Comments

Popular posts from this blog

Java Design Patterns

Java 8 Concepts with Examples