简体   繁体   English

如何实现阻塞ThreadPoolExecutor

[英]How to implement blocking ThreadPoolExecutor

I need to implement blocking ThreadPoolExecutor . 我需要实现阻塞ThreadPoolExecutor

This is a very crucial requirement in our enterprise application. 这是我们企业应用程序中非常关键的要求。

It would do something like if ThreadPoolExecutor.submit() or ThreadPoolExecutor.execute() method blocks until a thread gets freed up for picking up a new task. 它会像ThreadPoolExecutor.submit()ThreadPoolExecutor.execute()方法一样阻塞,直到线程被释放以获取新任务。

But in current implementation ThreadPoolExecutor.submit() and ThreadPoolExecutor.execute() methods throw RejectedExecutionException exception if all pooled threads get busy. 但是在当前实现中,如果所有池化线程都忙,则ThreadPoolExecutor.submit()ThreadPoolExecutor.execute()方法会抛出RejectedExecutionException异常。

For example following code throws RejectedExecutionException : 例如,以下代码抛出RejectedExecutionException

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class BlockingTPE {
    public static void main(String[] args) {
        ArrayBlockingQueue queue = new ArrayBlockingQueue(3);
        ThreadPoolExecutor tpExe = new ThreadPoolExecutor(1, 3, 30, TimeUnit.SECONDS, queue);
        int numJobs = 50;
        for (int i = 1; i <= numJobs; i++) {
            try {
                tpExe.submit(new WorkerThread(i));
                System.out.println("Added#" + (i));
            } catch (RejectedExecutionException e) {
                e.printStackTrace();
            }
        }
    }
}

class WorkerThread implements Runnable {
    int jobId;

    public WorkerThread(int jobId) {
        this.jobId = jobId;
    }

    public void run() {
        try {
            Thread.sleep(1000);
        }
        catch (Exception excep) {
        }
    }
}

As the javadoc of ThreadPoolExecutor states: 正如ThreadPoolExecutor的javadoc所述:

Creates a new ThreadPoolExecutor with the given initial parameters and default thread factory and rejected execution handler. 使用给定的初始参数和默认线程工厂以及拒绝的执行处理程序创建新的ThreadPoolExecutor。

The rejected executor handler is an instance of AbortPolicy which will be called if the queue does not accept another task. 被拒绝的执行程序处理程序是AbortPolicy一个实例,如果队列不接受另一个任务,它将被调用。 The behavior as of the javadoc: javadoc的行为:

Always throws RejectedExecutionException. 始终抛出RejectedExecutionException。

Hence the blocking queue does not have any effect for you. 因此阻塞队列对您没有任何影响。 I changed your code this way and it runs without any issues: 我以这种方式更改了代码,它运行没有任何问题:

public static void main(String[] args) {
    ThreadPoolExecutor executor = new ThreadPoolExecutor(
            1, 3, 30, TimeUnit.SECONDS, new ArrayBlockingQueue(3));
    try {
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        int numJobs = 50;
        for (int i = 1; i <= numJobs; i++) {
            try {
                executor.submit(new WorkerThread(i));
                System.out.println("Added#" + (i));
            } catch (RejectedExecutionException e) {
                e.printStackTrace();
            }
        }
    } finally {
        executor.shutdown();
    }
}

The decision you have to make is: 你必须做出的决定是:

  • use an unbound queue to support all delayed tasks. 使用未绑定的队列来支持所有延迟的任务。 For example LinkedBlockingQueue . 例如LinkedBlockingQueue
  • use a bound queue and let the current thread execute the task which does not fit into the full queue. 使用绑定队列,让当前线程执行不适合完整队列的任务。 For example see the code I posted along my answer. 例如,请参阅我在答案中发布的代码。
  • discard tasks if the bounded queue is full. 如果有界队列已满,则丢弃任务。 For example use ThreadPoolExecutor.DiscardPolicy as rejected execution handler. 例如,使用ThreadPoolExecutor.DiscardPolicy作为被拒绝的执行处理程序。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM