如何实现阻塞线程池执行器?

时间:2017-06-20 10:36:31

标签: java multithreading threadpoolexecutor

我们有一个大型文本文件,其中每行需要密集的process。设计是使用class来读取文件,并通过thread将每行的处理委托给thread pool。一旦池中没有空闲线程进行处理,就应该阻止文件阅读器类读取下一行。所以我需要一个blocking thread pool

在当前实现中,ThreadPoolExecutor.submit()ThreadPoolExecutor.execute()方法在配置的#个线程忙碌后抛出RejectedExecutionException异常,如下面的代码片段所示。

public class BlockingTp {

    public static void main(String[] args) {
        ArrayBlockingQueue arrayBlockingQueue = new ArrayBlockingQueue(3);
        ThreadPoolExecutor executorService= new ThreadPoolExecutor(1, 3, 30, TimeUnit.SECONDS, arrayBlockingQueue);
        int Jobs = 10;
        System.out.println("Starting application with " + Jobs + " jobs");
        for (int i = 1; i <= Jobs; i++)
            try {
                executorService.submit(new WorkerThread(i));
                System.out.println("job added " + (i));
            } catch (RejectedExecutionException e) {
                System.err.println("RejectedExecutionException");
            }
    }
}

class WorkerThread implements Runnable {
    int job;
    public WorkerThread(int job) {
        this.job = job;
    }
    public void run() {
        try {
            Thread.sleep(1000);
        } catch (Exception excep) {
        }
    }
}

以上程序的输出

Starting application to add 10 jobs
Added job #1
Added job #2
Added job #3
Added job #4
Added job #5
Added job #6
RejectedExecutionException
RejectedExecutionException
RejectedExecutionException
RejectedExecutionException

有人可以提出一些建议,即如何实施阻止线程池

4 个答案:

答案 0 :(得分:1)

  

有人可以抛出一些亮光,即我如何实现阻塞线程池。

您需要在执行器服务上设置拒绝执行处理程序。

BlockingQueue arrayBlockingQueue = new ArrayBlockingQueue(3);
ThreadPoolExecutor executorService =
     new ThreadPoolExecutor(1, 3, 30, TimeUnit.SECONDS, arrayBlockingQueue);
// when the blocking queue is full, this tries to put into the queue which blocks
executorService.setRejectedExecutionHandler(new RejectedExecutionHandler() {
    @Override
    public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
        try {
            // block until there's room
            executor.getQueue().put(r);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            throw new RejectedExecutionException("Producer thread interrupted", e);
        }
    }
});

因此,不是TRE抛出RejectedExecutionException,而是调用拒绝处理程序,而处理程序又会尝试将作业放回队列中。这会阻止来电者。

答案 1 :(得分:0)

让我们再看一下你的代码:

for (int i = 1; i <= Jobs; i++)
  try {
    tpExe.submit(new WorkerThread(i));
    System.out.println("job added " + (i));
  } catch (RejectedExecutionException e) {
    System.err.println("RejectedExecutionException");
  }

所以 - 当你尝试提交,并且池正忙时,会抛出该异常。如果你想环绕它,它可能看起来像:

public void yourSubmit(Runnable whatever) {
  boolean submitted = false;
  while (! submitted ) {
    try {
      tpExe.submit(new WorkerThread(whatever));
      submitted = true;
    } catch (RejectedExecutionException re) {
      // all threads busy ... so wait some time
      Thread.sleep(1000);
    }

换句话说:将该例外用作&#34;标记&#34;提交目前是不可能的。

答案 2 :(得分:0)

这适合我。

class handler implements RejectedExecutionHandler{
    @Override
            public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
                try {
                    executor.getQueue().put(r);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }

            }

答案 3 :(得分:0)

您可以使用信号量来控制resource.Reader将通过获取信号量来读取和创建异步任务。如果每个线程都忙,读者线程将等待线程可用。

public class MyExecutor {
    private final Executor exec;
    private final Semaphore semaphore;

    public BoundedExecutor(Executor exec, int bound) {
        this.exec = exec;
        this.semaphore = new Semaphore(bound);
    }

    public void submitTask(final Runnable command)
            throws InterruptedException, RejectedExecutionException {
        semaphore.acquire();
        try {
            exec.execute(new Runnable() {
                public void run() {
                    try {
                        command.run();
                    } finally {
                        semaphore.release();
                    }
                }
            });
        } catch (RejectedExecutionException e) {
            semaphore.release();
            throw e;
        }
    }
}