package com.interview.multithreaded;
import java.util.LinkedList;
import java.util.Queue;
class ThreadPool {
public Thread run(Runnable runnable) {
Thread t = new Thread(runnable);
t.start();
return t;
}
}
/**
* Facebook interview question
* Implement a non block run which takes as many runnables as given but only
* runs a specified number of threads.
* You can also update maxSize in between which will change number of threads executing
* http://tutorials.jenkov.com/java-concurrency/thread-pools.html
*/
public class ThreadPoolImpl {
private int maxSize = 0;
ThreadPool threadPool;
public ThreadPoolImpl(int size, ThreadPool threadPool) {
maxSize = size;
this.threadPool = threadPool;
}
public void setMax(int size){
System.out.print("Setting max size " + size);
if(maxSize == 0){
maxSize = size;
execute();
}else{
maxSize = size;
}
}
private int currentSize = 0;
private Queue<Runnable> waitingThreads = new LinkedList<Runnable>();
private boolean isExecuting = false;
private Object monitor = new Object();
public void run(Runnable thread) {
synchronized (monitor) {
waitingThreads.offer(thread);
execute();
}
}
private void execute() {
if (!isExecuting) {
isExecuting = true;
ExecutingRunnable runnable = new ExecutingRunnable();
threadPool.run(runnable);
}
}
class ExecutingRunnable implements Runnable {
@Override
public void run() {
while (true) {
synchronized(monitor){
if(maxSize ==0){
isExecuting = false;
break;
}
}
while (waitingThreads.size() > 0) {
synchronized(monitor){
if(maxSize ==0){
isExecuting = false;
break;
}
}
if (currentSize < maxSize) {
currentSize++;
Runnable run = waitingThreads.poll();
RunnableThreads r = new RunnableThreads(run);
threadPool.run(r);
}
}
synchronized (monitor) {
if (waitingThreads.size() == 0) {
isExecuting = false;
break;
}
}
// System.out.println("Looping");
}
}
}
class RunnableThreads implements Runnable {
private Runnable r;
RunnableThreads(Runnable r) {
this.r = r;
}
@Override
public void run() {
r.run();
currentSize--;
}
}
public static void main(String args[]) throws InterruptedException{
ThreadPool threadPool = new ThreadPool();
ThreadPoolImpl impl = new ThreadPoolImpl(4, threadPool);
int i;
for(i=0; i < 10; i++){
MyRunnable runnable = new MyRunnable(i);
impl.run(runnable);
}
Thread.sleep(5000);
impl.setMax(0);
Thread.sleep(10000);
impl.setMax(6);
for(;i < 15;i++){
MyRunnable runnable = new MyRunnable(i);
impl.run(runnable);
}
}
}
class MyRunnable implements Runnable{
int index = 0;
MyRunnable(int index){
this.index =index;
}
@Override
public void run() {
System.out.println("Start of index " + index);
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
System.out.println("Exception " + index + " " + e);
}
System.out.println("End of index " + index);
}
}