另外我的理解是,如果任务可用,它将被执行.
我不明白的是以下内容:
public class MyThreadPoolExecutor { private static ThreadPoolExecutor executor; public MyThreadPoolExecutor(int min,int max,int idleTime,BlockingQueue<Runnable> queue){ executor = new ThreadPoolExecutor(min,max,10,TimeUnit.MINUTES,queue); //executor.prestartAllCoreThreads(); } public static void main(String[] main){ BlockingQueue<Runnable> q = new LinkedBlockingQueue<Runnable>(); final String[] names = {"A","B","C","D","E","F"}; for(int i = 0; i < names.length; i++){ final int j = i; q.add(new Runnable() { @Override public void run() { System.out.println("Hi "+ names[j]); } }); } new MyThreadPoolExecutor(10,20,1,q); try { TimeUnit.SECONDS.sleep(5); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } /*executor.execute(new Runnable() { @Override public void run() { System.out.println("++++++++++++++"); } }); */ for(int i = 0; i < 100; i++){ final int j = i; q.add(new Runnable() { @Override public void run() { System.out.println("Hi "+ j); } }); } } }
除非我取消注释executor.prestartAllCoreThreads();否则此代码不会执行任何操作.在构造函数中或者我调用runnable的执行来打印System.out.println(“”); (它也被注释掉了).
为什么?
引用(我的重点):
By default,even core threads are initially created and started only
when new tasks arrive,but this can be overridden dynamically using
method prestartCoreThread() or prestartAllCoreThreads(). You probably
want to prestart threads if you construct the pool with a non-empty
queue.
好.所以我的队列不是空的.但我创建了执行程序,我睡觉然后我将新的Runnables添加到队列中(在循环中为100).
当新任务到来时,这个循环不计算在内吗?
为什么它不起作用,我必须预启动或明确地调用执行?
解决方法
我再说一遍,工人是与工作队列互动的工人.它们仅在通过execute传递时按需生成. (或者它上面的层,例如invokeAll,submit等)如果它们没有启动,那么你添加到队列中的工作量并不重要,因为没有任何工作人员启动就没有检查它.
ThreadPoolExecutor不会在必要之前生成工作线程,或者如果您通过方法prestartAllCoreThreads和prestartCoreThread抢占它们的创建.如果没有工作程序启动,那么您的队列中的任何工作都无法完成.
添加初始执行的原因是它强制创建唯一的核心工作线程,然后该线程可以开始处理队列中的工作.您还可以调用prestartCoreThread并接收类似的行为.如果要启动所有工作程序,则必须调用prestartAllCoreThreads或通过execute提交该数量的任务.
请参阅下面的执行代码.
/** * Executes the given task sometime in the future. The task * may execute in a new thread or in an existing pooled thread. * * If the task cannot be submitted for execution,either because this * executor has been shutdown or because its capacity has been reached,* the task is handled by the current {@code RejectedExecutionHandler}. * * @param command the task to execute * @throws RejectedExecutionException at discretion of * {@code RejectedExecutionHandler},if the task * cannot be accepted for execution * @throws NullPointerException if {@code command} is null */ public void execute(Runnable command) { if (command == null) throw new NullPointerException(); /* * Proceed in 3 steps: * * 1. If fewer than corePoolSize threads are running,try to * start a new thread with the given command as its first * task. The call to addWorker atomically checks runState and * workerCount,and so prevents false alarms that would add * threads when it shouldn't,by returning false. * * 2. If a task can be successfully queued,then we still need * to double-check whether we should have added a thread * (because existing ones died since last checking) or that * the pool shut down since entry into this method. So we * recheck state and if necessary roll back the enqueuing if * stopped,or start a new thread if there are none. * * 3. If we cannot queue task,then we try to add a new * thread. If it fails,we know we are shut down or saturated * and so reject the task. */ int c = ctl.get(); if (workerCountOf(c) < corePoolSize) { if (addWorker(command,true)) return; c = ctl.get(); } if (isRunning(c) && workQueue.offer(command)) { int recheck = ctl.get(); if (! isRunning(recheck) && remove(command)) reject(command); else if (workerCountOf(recheck) == 0) addWorker(null,false); } else if (!addWorker(command,false)) reject(command); }