打字猴:1.700450601e+09
1700450601
1700450602 //生成一个最大为nThreads的线程池执行器
1700450603
1700450604 return new ThreadPoolExecutor(nThreads, nThreads,0L, TimeUnit.
1700450605
1700450606 MILLISECONDS, new LinkedBlockingQueue<Runnable>());
1700450607
1700450608 }
1700450609
1700450610 }
1700450611
1700450612 这里使用了LinkedBlockingQueue作为任务队列管理器,所有等待处理的任务都会放在该队列中,需要注意的是,此队列是一个阻塞式的单端队列。线程池建立好了,那就需要线程在其中运行了,线程池中的线程是在submit第一次提交任务时建立的,代码如下:
1700450613
1700450614 public Future<?>submit(Runnable task){
1700450615
1700450616 //检查任务是否为null
1700450617
1700450618 if(task==null)throw new NullPointerException();
1700450619
1700450620 //把Runnable任务包装成具有返回值的任务对象,不过此时并没有执行,只是包装
1700450621
1700450622 RunnableFuture<Object>ftask=newTaskFor(task, null);
1700450623
1700450624 //执行此任务
1700450625
1700450626 execute(ftask);
1700450627
1700450628 //返回任务预期执行结果
1700450629
1700450630 return ftask;
1700450631
1700450632 }
1700450633
1700450634 此处的代码关键是execute方法,它实现了三个职责。
1700450635
1700450636 创建足够多的工作线程数,数量不超过最大线程数量,并保持线程处于运行或等待状态。
1700450637
1700450638 把等待处理的任务放到任务队列中。
1700450639
1700450640 从任务队列中取出任务来执行。
1700450641
1700450642 其中此处的关键是工作线程的创建,它也是通过new Thread方式创建的一个线程,只是它创建的并不是我们的任务线程(虽然我们的任务实现了Runnable接口,但它只是起一个标志性的作用),而是经过包装的Worker线程,代码如下:
1700450643
1700450644 private final class Worker implements Runnable{
1700450645
1700450646 //运行一次任务
1700450647
1700450648 private void runTask(Runnable task){
1700450649
1700450650 //这里的task才是我们自定义实现Runnable接口的任务
[ 上一页 ]  [ :1.700450601e+09 ]  [ 下一页 ]