0

I got very confused by reading Thread Pooling. I learnt the concept, how they actually works. But I confused in the part , how to code this.

I searched a lot on the net. Finally I got a blog, that have codes , given below,

CONDITION IS, NOT TO USE IN-BUILT CLASS

Code 1

public class ThreadPool {

  private BlockingQueue taskQueue = null;
  private List<PoolThread> threads = new ArrayList<PoolThread>();
  private boolean isStopped = false;

  public ThreadPool(int noOfThreads, int maxNoOfTasks){
    taskQueue = new BlockingQueue(maxNoOfTasks);

    for(int i=0; i<noOfThreads; i++){
      threads.add(new PoolThread(taskQueue));
    }
    for(PoolThread thread : threads){
      thread.start();
    }
  }

  public void synchronized execute(Runnable task){
    if(this.isStopped) throw
      new IllegalStateException("ThreadPool is stopped");

    this.taskQueue.enqueue(task);
  }

  public synchronized void stop(){
    this.isStopped = true;
    for(PoolThread thread : threads){
      thread.stop();
    }
  }

}

Code 2

public class PoolThread extends Thread {
  private BlockingQueue taskQueue = null;
  private boolean       isStopped = false;
  public PoolThread(BlockingQueue queue){
    taskQueue = queue;
  }
  public void run(){
    while(!isStopped()){
      try{
        Runnable runnable = (Runnable) taskQueue.dequeue();
        runnable.run();
      } catch(Exception e){
        //log or otherwise report exception,
        //but keep pool thread alive.
      }
    }
  }
  public synchronized void stop(){
    isStopped = true;
    this.interrupt(); //break pool thread out of dequeue() call.
  }
  public synchronized void isStopped(){
    return isStopped;
  }
}

Code 3:-

public class BlockingQueue {

  private List queue = new LinkedList();
  private int  limit = 10;

  public BlockingQueue(int limit){
    this.limit = limit;
  }

  public synchronized void enqueue(Object item)
  throws InterruptedException  {
    while(this.queue.size() == this.limit) {
      wait();
    }
    if(this.queue.size() == 0) {
      notifyAll();
    }
    this.queue.add(item);
  }

  public synchronized Object dequeue()
  throws InterruptedException{
    while(this.queue.size() == 0){
      wait();
    }
    if(this.queue.size() == this.limit){
      notifyAll();
    }

    return this.queue.remove(0);
  }    
}

I tried to understand , what this code do. But I dont get the flow of this code. Can you help me to understand this code.

Mainly I have problems in **Code 2 :- run method**

Why execute method's argument are of Runnable type?

How input array given to this code??

Help me.

Thanks in advance.

devsda
  • 4,112
  • 9
  • 50
  • 87
  • 1
    Why do you have to write your own thread pool? Easiest to use the Executors.*ThreadPool() methods to create a thread pool and then use the submit(*) methods on that to submit either a Callable or a Runnable. – allprog Jan 22 '13 at 13:20
  • @allprog: I made that code, that code is easy to build. But my teacher asked to build this without using inbuilt class. Thats why I posted this. – devsda Jan 22 '13 at 13:25
  • Nice, you make the community check the homework. :) Unfortunately, doing the ExecutorService right is hard. If you provide the asynchronous Future interface with cancellation, then you'll have to be really careful. You should look at the JDK source code for correct implementation. It will be a lot more complex than what you have now. – allprog Jan 22 '13 at 15:52
  • @allprog: No, I am not make community to check code. I spent a lot time with this, and finally I have problem in the small module, then only I asked this answer. I will take care of ypur advice. Thanks:) – devsda Jan 22 '13 at 16:15
  • Take my words easy. Better ask than not knowing the answer. :) You should use generics for the BlockingQueue as well but don't use Object type for enqueue and dequeue in any case. It will blow your code! There is an implementation for this functionality with the same name in the JDK, cannot you use that? I think the ExecutorService is (implemented correctly) already way more complex than a simple home work or assignment should be. – allprog Jan 22 '13 at 19:43
  • To answer your questions: 1. Runnable is needed to be able to run what you submit. It could be anything else but it must conform to an interface of your choice. What would you do with an Object? What could be run on it? Nothing. Generally we use Runnable and Callable for these purposes. 2. I'm not sure I understand what you mean by input array. I suppose you need to submit your array of Runnables to the BlockingQueue and the worker threads which grind them in the run() loops. – allprog Jan 22 '13 at 19:47
  • @allprog : Cn we chat now, if you have time – devsda Jan 22 '13 at 20:05
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/23166/discussion-between-freakycheeky-and-allprog) – devsda Jan 22 '13 at 20:07
  • @allprog : open our chat link, I leave one message for you. nd answer that , please. – devsda Jan 23 '13 at 03:06
  • http://stackoverflow.com/questions/14482268/doubts-in-the-code-of-thread-pool-implementation#comment20178834_14482268 Answer this please. I am on the way to get clear image of thread pool in both coding and conceptual sense. – devsda Jan 23 '13 at 14:49

2 Answers2

2
  public void run(){
    while(!isStopped()){

Loop until the thread pool is stopped.

      try{
        Runnable runnable = (Runnable) taskQueue.dequeue();

Pull the head task off the task queue.

        runnable.run();

Run the task.

      } catch(Exception e){
        //log or otherwise report exception,
        //but keep pool thread alive.

Do nothing special if the task throws an exception, just don't pass it on.

      }
    }
  }
David Schwartz
  • 179,497
  • 17
  • 214
  • 278
  • ` public PoolThread(BlockingQueue queue){ taskQueue = queue; }` As far as I understand, these lines works to give copy of taskqueue to all thread workers. Am I right ? – devsda Jan 22 '13 at 13:31
  • Tell me one more thing, how we give inut array to **code 1** . Because to start we have to call execute method of code 1. – devsda Jan 22 '13 at 13:38
  • @FreakyCheeky: First question: Yes. Each thread gets a reference to the same queue. Second question: You call the execute function and it puts the task on the shared queue. – David Schwartz Jan 22 '13 at 13:51
  • Tell me one thing, why execute ethod parameter is of Runnable type?? I dont understand this. – devsda Jan 22 '13 at 18:45
  • It's explained in the documentation for [runnable](http://docs.oracle.com/javase/1.4.2/docs/api/java/lang/Runnable.html). It's intended for precisely this purpose. – David Schwartz Jan 22 '13 at 18:49
  • But I have to pass array of N size. How it will take care of that?? – devsda Jan 22 '13 at 18:58
  • Can you add that part in your answer also? – devsda Jan 22 '13 at 19:00
  • I'm not sure what you're talking about. Pass an array to what? – David Schwartz Jan 22 '13 at 19:11
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/23162/discussion-between-freakycheeky-and-david-schwartz) – devsda Jan 22 '13 at 19:13
  • Can we chat on this topic please. – devsda Jan 22 '13 at 19:17
  • Schawartz: where this `runnable.run();` run method declared? – devsda Jan 23 '13 at 04:20
  • @FreakyCheeky: See the documentation for [runnable](http://docs.oracle.com/javase/1.4.2/docs/api/java/lang/Runnable.html). – David Schwartz Jan 23 '13 at 04:52
  • http://stackoverflow.com/questions/14482268/doubts-in-the-code-of-thread-pool-implementation#comment20178834_14482268 Answer this please. I am on the way to get clear image of thread pool in both coding and conceptual sense. – devsda Jan 23 '13 at 14:51
1

Edit:

I now understand that this is a class project but I'll leave my answer for posterity.

If you are trying to use thread-pools under Java then all of this has been already implemented for you by the java.util.concurrent.* classes. Other answers address and explain your specific code.

For example, this is what you need to setup a thread pool using the ExecutorService code. Underneath the covers the ExecutorService handles the threads and uses a LinkedBlockingQueue. You define the MyJob class which implements 'Runnable' and does the work that is run by the threads in the pool. It can be a short or a long running task depending on what you need.

// create a thread pool with 10 workers
ExecutorService threadPool = Executors.newFixedThreadPool(10);
// or you can create an open-ended thread pool
// ExecutorService threadPool = Executors.newCachedThreadPool();
// define your jobs somehow
for (MyJob job : jobsToDo) {
    threadPool.submit(job);
}
// once we have submitted all jobs to the thread pool, it should be shutdown
threadPool.shutdown();
...
public class MyJob implements Runnable {
    // you can construct your jobs and pass in context for them if necessary
    public MyJob(String someContext) {
        ...
    }
    public void run() {
        // process the job
    }
}
Gray
  • 115,027
  • 24
  • 293
  • 354
  • Actually I made this code by using Built-in class, but my teacher said to me to do this by own, without using Built-in class – devsda Jan 22 '13 at 13:34