Java ThreadPoolExecutor修复了具有自定义行为的线程池

Java ThreadPoolExecutor修复了具有自定义行为的线程池,java,multithreading,threadpool,threadpoolexecutor,Java,Multithreading,Threadpool,Threadpoolexecutor,我不熟悉这个话题。。。我正在使用由Executors.newFixedThreadPool(10)创建的ThreadPoolExecutor,在池满后,我开始得到一个RejectedExecutionException。 有没有办法“强制”执行者将新任务置于“等待”状态,而不是拒绝它并在释放池时启动它 谢谢 关于这个问题 如果使用执行器,则涉及的代码行。newFixedThreadPool(10)它对任务进行排队,并等待线程准备就绪 这种方法是可行的 public static Executo

我不熟悉这个话题。。。我正在使用由Executors.newFixedThreadPool(10)创建的ThreadPoolExecutor,在池满后,我开始得到一个RejectedExecutionException。 有没有办法“强制”执行者将新任务置于“等待”状态,而不是拒绝它并在释放池时启动它

谢谢

关于这个问题


如果使用执行器,则涉及的代码行

。newFixedThreadPool(10)它对任务进行排队,并等待线程准备就绪

这种方法是可行的

public static ExecutorService newFixedThreadPool(int nThreads) {
    return new ThreadPoolExecutor(nThreads, nThreads,
                                  0L, TimeUnit.MILLISECONDS,
                                  new LinkedBlockingQueue<Runnable>());
}

可以说明这种情况的测试类

public static void main(String... args) {
    ExecutorService es = Executors.newFixedThreadPool(2);
    for (int i = 0; i < 1000 * 1000; i++)
        es.submit(new SleepOneSecond());

    System.out.println("Queue length " + ((ThreadPoolExecutor) es).getQueue().size());
    es.shutdown();
    System.out.println("After shutdown");
    try {
        es.submit(new SleepOneSecond());
    } catch (Exception e) {
        e.printStackTrace(System.out);
    }
}

static class SleepOneSecond implements Callable<Void> {
    @Override
    public Void call() throws Exception {
        Thread.sleep(1000);
        return null;
    }
}

线程很可能调用
exit
,将
mStopped
设置为false并关闭执行器,但是:

    <> LI>您的运行线程可能在<代码>的中间,而(.MSTROUND)循环,并尝试将任务提交到已被代码“退出”/代码> < /LI>关闭的执行器中。
  • while
    中的条件返回true,因为对
    mStopped
    所做的更改不可见(您不在该标志周围使用任何形式的同步)
我建议:

  • 使
    mStopped
    volatile
  • 处理执行器在循环中途关闭的情况(例如,通过捕获ReaveCeExeCeExtExpRebug,或者可能更好:在while循环之后关闭执行程序,而不是在退出方法中关闭它)。
基于前面的建议,您可以使用阻塞队列构造固定大小的
ThreadPoolExecutor
。如果您随后提供自己的
RejectedExecutionHandler
,将任务添加到阻塞队列,则其行为将如所述

下面是一个如何构建这样一个执行者的示例:

int corePoolSize    = 10;
int maximumPoolSize = 10;
int keepAliveTime   =  0;
int maxWaitingTasks = 10;

ThreadPoolExecutor blockingThreadPoolExecutor = new ThreadPoolExecutor(
        corePoolSize, maximumPoolSize,
        keepAliveTime, TimeUnit.SECONDS,
        new ArrayBlockingQueue<Runnable>(maxWaitingTasks),
        new RejectedExecutionHandler() {
            @Override
            public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
                try {
                    executor.getQueue().put(r);
                } catch (InterruptedException e) {
                    throw new RuntimeException("Interrupted while submitting task", e);
                }
            }
        });
int corePoolSize=10;
int maximumPoolSize=10;
int keepAliveTime=0;
int maxWaitingTasks=10;
ThreadPoolExecutor blockingThreadPoolExecutor=新的ThreadPoolExecutor(
corePoolSize、maximumPoolSize、,
keepAliveTime,TimeUnit.SECONDS,
新的ArrayBlockingQueue(maxWaitingTasks),
新的RejectedExecutionHandler(){
@凌驾
public void rejectedExecution(可运行的r、线程池执行器执行器){
试一试{
executor.getQueue().put(r);
}捕捉(中断异常e){
抛出新的RuntimeException(“提交任务时中断”,e);
}
}
});

如果我理解正确,您可以使用固定数量的线程创建线程池,但您可能需要向线程池提交更多任务。我会根据请求计算keepAliveTime并动态设置它。这样,您就不会拒绝ExecutionException

比如说

long keepAliveTime=((applications.size()*60)/固定线程数)*1000; setKeepAliveTime(keepAliveTime,TimeUnit.ms)

其中,应用程序是每次都可能不同的任务的集合


如果你知道这项任务的平均时间,这应该可以解决你的问题。

不过,我得到了RejectedExecutionException,正如您在这里看到的,这是一行代码,给出了@SimoneMargaritelli问题。当使用
newFixedThreadPool
时,如果您试图在
关闭
方法后向执行器提交任务,那么您应该得到
RejectedExecutionException
的唯一原因就是已调用。鉴于该池仅运行过31个任务,我怀疑其未满。此外,corePoolSize为0表示它已被关闭,这将触发拒绝。@SimoneMargaritelli顺便说一句,您不需要强制转换到ThreadPoolExecutor,我会将其保留为接口ExecutorService。您是否找到了此问题的解决方案?
Queue length 999998
After shutdown
java.util.concurrent.RejectedExecutionException: Task java.util.concurrent.FutureTask@e026161 rejected from java.util.concurrent.ThreadPoolExecutor@3e472e76[Shutting down, pool size = 2, active threads = 2, queued tasks = 999998, completed tasks = 0]
    at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2013)
    at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:816)
    at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1337)
    at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:132)
    at Main.main(Main.java:17)
int corePoolSize    = 10;
int maximumPoolSize = 10;
int keepAliveTime   =  0;
int maxWaitingTasks = 10;

ThreadPoolExecutor blockingThreadPoolExecutor = new ThreadPoolExecutor(
        corePoolSize, maximumPoolSize,
        keepAliveTime, TimeUnit.SECONDS,
        new ArrayBlockingQueue<Runnable>(maxWaitingTasks),
        new RejectedExecutionHandler() {
            @Override
            public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
                try {
                    executor.getQueue().put(r);
                } catch (InterruptedException e) {
                    throw new RuntimeException("Interrupted while submitting task", e);
                }
            }
        });