代码之家  ›  专栏  ›  技术社区  ›  Sarmun

指定ThreadPoolExecutor问题

  •  5
  • Sarmun  · 技术社区  · 17 年前

    我尝试了新的 ThreadPoolExecutor(5, 20, 60L, TimeUnit.SECONDS, queue)

    new LinkedBlockingQueue() // never runs more than 5 threads
    new LinkedBlockingQueue(1000000) // runs more than 5 threads, only when there is more than 1000000 tasks waiting
    new ArrayBlockingQueue(1000000) // runs more than 5 threads, only when there is more than 1000000 tasks waiting
    new SynchronousQueue() // no tasks can wait, after 20, they are rejected
    

    3 回复  |  直到 17 年前
        1
  •  5
  •   Stu Thompson Helter Scelter    17 年前

    ThreadPoolExecutor

    • 缺少返回的Future对象 submit()
    • StusMagicExecutor 那么这可能不是问题。(“May”是关键词。)一个选择可能是让你提交的任务戳 在他们完成之后?

    斯图的魔法执行者:

    public class StusMagicExecutor extends ThreadPoolExecutor {
        private BlockingQueue<Runnable> secondaryQueue = new LinkedBlockingQueue<Runnable>();  //capacity is Integer.MAX_VALUE.
    
        public StusMagicExecutor() {
            super(5, 20, 60L, SECONDS, new SynchronousQueue<Runnable>(true), new RejectionHandler());  
        }
        public void queueRejectedTask(Runnable task) {
            try {
                secondaryQueue.put(task);
            } catch (InterruptedException e) {
                // do something
            }
        }
        public Future submit(Runnable newTask) {
            //drain secondary queue as rejection handler populates it
            Collection<Runnable> tasks = new ArrayList<Runnable>();
            secondaryQueue.drainTo(tasks);
    
            tasks.add(newTask);
    
            for (Runnable task : tasks)
                 super.submit(task);
    
            return null; //does not return a future!
        }
    }
    
    class RejectionHandler implements RejectedExecutionHandler {
        public void rejectedExecution(Runnable runnable, ThreadPoolExecutor executor) {
            ((StusMagicExecutor)executor).queueRejectedTask(runnable);
        }
    }
    
        2
  •  1
  •   skaffman    17 年前

    ThreadPoolExecutor corePoolSize 线程已创建,只有在队列已满时才会创建新线程。所以如果你设置 core max 到20岁,你永远不会得到你想要的行为。

    但是,如果您同时设置了这两个 和

        3
  •  1
  •   Cole Stanfield    16 年前

    我认为这个问题是类的一个缺点,考虑到构造函数参数组合,它非常具有误导性。这是一个从SwingWorker的内部ThreadPoolExecutor中提取的解决方案,我将其制作成了一个顶级类。它没有最小值,但至少使用了一个上限。我唯一不知道的是,锁定执行会对性能产生什么影响。

    public class BoundedThreadPoolExecutor extends ThreadPoolExecutor {
        private final ReentrantLock pauseLock = new ReentrantLock();
        private final Condition unpaused = pauseLock.newCondition();
        private boolean isPaused = false;
        private final ReentrantLock executeLock = new ReentrantLock();
    
        public BoundedThreadPoolExecutor(int maximumPoolSize,
                long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) {
            super(0, maximumPoolSize, keepAliveTime, unit, workQueue);
        }
    
        public BoundedThreadPoolExecutor(int maximumPoolSize,
                long keepAliveTime, TimeUnit unit,
            BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory) {
            super(0, maximumPoolSize, keepAliveTime, unit, workQueue,
                    threadFactory);
        }
    
        public BoundedThreadPoolExecutor(int maximumPoolSize,
                long keepAliveTime, TimeUnit unit,
                BlockingQueue<Runnable> workQueue, RejectedExecutionHandler handler) {
            super(0, maximumPoolSize, keepAliveTime, unit, workQueue,
                    handler);
        }
    
        public BoundedThreadPoolExecutor(int maximumPoolSize,
                long keepAliveTime, TimeUnit unit,
                BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory,
                RejectedExecutionHandler handler) {
            super(0, maximumPoolSize, keepAliveTime, unit, workQueue,
                    threadFactory, handler);
        }
    
        @Override
        public void execute(Runnable command) {
            executeLock.lock();
            try {
                pauseLock.lock();
                try {
                    isPaused = true;
                } finally {
                    pauseLock.unlock();
                }
                setCorePoolSize(getMaximumPoolSize());
                super.execute(command);
                setCorePoolSize(0);
                pauseLock.lock();
                try {
                    isPaused = false;
                    unpaused.signalAll();
                } finally {
                    pauseLock.unlock();
                }
            } finally {
                executeLock.unlock();
            }
        }
    
        @Override
        protected void afterExecute(Runnable r, Throwable t) {
            super.afterExecute(r, t);
            pauseLock.lock();
            try {
                while (isPaused) {
                    unpaused.await();
                }
            } catch (InterruptedException ignore) {
    
            } finally {
                pauseLock.unlock();
            }
        }
    }