如何创建生产者/消费者线程模式?

时间:2017-03-15 10:31:47

标签: java multithreading

我有多个workerThreads和一个producerThread。当我运行下面的代码时,很少运行工作线程。我得到的输入就像;

workToDo Size: 1
workToDo Size: 2
...
workToDo Size: 514
91 removed  //First remove output

workToDo列表正在增加。有没有办法减少工作线程的运行间隔?我想我在这里做错了。

我的主要方法;

WorkerThread workerThread = new WorkerThread();
WorkerThread workerThread2 = new WorkerThread();
WorkerThread workerThread3 = new WorkerThread();
ProducerThread producerThread = new ProducerThread();
workerThread.producerThread = producerThread;
workerThread2.producerThread = producerThread;
workerThread3.producerThread = producerThread;
producerThread.start();
workerThread.start();
workerThread2.start();
workerThread3.start();

的WorkerThread;

public class WorkerThread extends Thread {

  ProducerThread producerThread;

  @Override
  public void run() {
    while (true) {
        synchronized (producerThread) {
            try {
                producerThread.wait();
                System.out.println(producerThread.workToDo.remove(0) + " removed");
            } catch (InterruptedException ex) {
            }
        }
    }
  }
}

ProducerThread;

public class ProducerThread extends Thread {

  List<Integer> workToDo = new ArrayList();

  @Override
  public void run() {
    while (true) {
        synchronized (this) {
            workToDo.add((int)(Math.random() * 100));
            System.out.println("workToDo Size: " + workToDo.size());
            notifyAll();
        }
    }
  }
}

1 个答案:

答案 0 :(得分:2)

  

workToDo列表正在增加。有没有办法减少工作线程的运行间隔?我想我在这里做错了。

没有看到更多的代码,很难完全回答,但这似乎是一个典型的问题,当你的生产者线程可以比消费者处理它们更快地产生工作。您应该使用有界 BlockingQueue,这样您才能排队一定数量的请求,而不是用它们填充内存。

您应该考虑将ExecutorService classes与有界队列一起使用。例如:

// start a thread pool with 3 worker threads and a queue of 100
ExecutorService threadPool =
      new ThreadPoolExecutor(3, 3, 0L, TimeUnit.MILLISECONDS,
                             new ArrayBlockingQueue<Runnable>(100));
// to get the producer to _block_ instead of rejecting the job you need a handler
threadPool.setRejectedExecutionHandler(new RejectedExecutionHandler() {
     public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
         // this will cause the producer to block until there is room in queue
         executor.getQueue().add(r);
     }
});

你的生产者线程,如果你将线程数增加到4,它也可以是在threadPool中运行的作业,然后只需将Runnable个作业提交给你的线程池,由3个工作线程处理。如果3忙,那么它将在ArrayBlockingQueue中排队请求。一旦100(随意更改该号码)作业排队,生产者将阻止,直到另一个作业完成。

使用ExecutorServiceBlockingQueue意味着所有难以理解的等待和通知逻辑都会为您完成。