Java线程池(一):初识

一、什么是线程池?html

  简单粗暴的理解就是:装着一个或多个线程的容器,咱们称这个容器为线程池。java

  在现实世界中,有着各类各样的“池”,例如游泳池、花池等等。那花池来讲,里面种满了各类各样的鲜花,花池自己要作的就是提供一片空地,里面的鲜花是园丁来种植、浇水。不一样于花池,线程池不单单须要提供一个能够装线程的容器,同时还要承担起管理容器里中线程的职责(例如,新建线程、使用线程等)。segmentfault

  一个简单的线程池应该至少包含下面4个部分:并发

    (1)线程池管理器:建立、销毁并管理线程池,将工做线程放入线程池中函数

    (2)工做线程:一个能够循环执行任务的线程,在没有任务时进行等待测试

    (3)任务队列:将没有处理的任务放在任务队列中,提供一种缓冲机制this

    (4)任务接口:主要用来规定任务的的入口、任务完成后的收尾工做、任务的执行状态等,工做线程经过该接口调度任务的执行编码

 

  下面举一个简单的例子来理解线程池的工做:spa

    将线程比做一个机器人,一个线程池就是有不少机器人的工厂,工厂经过新建机器人、分配任务给机器人等方式管理者工厂中的全部机器人。初始时,工厂中并无机器人。当工厂接到第一个任务时,工厂的管理人员首先新建机器人1号,而后再将任务分配给机器人1号,机器人1号收到任务的命令后就开始工做了。紧接着,工厂接到了第二个任务,管理人员又新建了机器人2号,将第二个任务分配给了机器人2号。当工厂再次接到新的任务时,重复前面的过程。然而,工厂不可能无限制地新建机器人:新建机器人也是须要材料和消耗资源的,资源是有限的;当有新的任务时,前面新建的机器人可能已经完成了交给它的任务而处于空闲状态,所以能够将新的任务分配给处于休息状态的机器人。当工厂中全部的机器人都处于工做状态时,又来了新的任务,怎么办呢?因而,工厂管理者设置了一个任务等候区,新来的任务按顺序在等候区排队。当有机器人完成了任务时,从任务队列中取出一个任务,分配给空闲的机器人,让机器人从新处于工做状态。.net

 

二、为何要使用线程池?

   从前面工厂的例子中能够看出,线程池为咱们带来了如下好处:

    (1)分摊建立线程的开销,加快对请求的响应速度。接到一个任务时,新建了一个线程用于完成任务。当任务完成后,线程处于空闲状态,后面再有新的任务时,没必要再新建线程,处于空闲状态的线程能够直接投入工做,省去了新建线程了过程,加快了对请求的响应速度。因为对线程实现了重用,新建线程的开销就被分摊到了多个任务上,线程被重用的次数越多,平均分摊到每一个任务中的线程建立的开销就越少。

    (2)解决了资源不足的问题。线程是须要资源的,而资源又是有限的,经过控制线程的数目,避免出现资源不足的问题。

 

三、如何使用线程池?

  线程池有着上面的优点,能够本身编码实现一个线程池。然而,编码实现线程池自己就是一项工做量不小的任务,而咱们的工做重心是要完成实际的业务。同时,本身编码实现的线程池的正确性、可靠性与稳定性难以保证。因而,大师Doug Lea编写并开源了一个并发程序的代码库,在JDK 1.5以后已加入JDK的豪华套餐,为 java.util.concurrent包。

 

  在Java中,线程池类为java.util.concurrent.ThreadPoolExecutor,能够经过该类建立咱们须要的线程池:

1     public ThreadPoolExecutor(int corePoolSize,
2                               int maximumPoolSize,
3                               long keepAliveTime,
4                               TimeUnit unit,
5                               BlockingQueue<Runnable> workQueue,
6                               RejectedExecutionHandler handler)

参数说明:

  corePoolSize : 线程池维护线程的数量(the number of threads to keep in the pool, even if they are idle.)

  maximumPoolSize : 线程池维护线程的最大数量(the maximum number of threads to allow in the pool.)

  keepAliveTime : 线程池中的线程容许的最大空闲时间(when the number of threads is greater than the core, this is the maximum time that excess idle threads will wait for new tasks before terminating.)

  unit : 参数keepAliveTime的时间单位 (the time unit for the keepAliveTime argument.)

  workQueue : 任务缓冲队列(the queue to use for holding tasks before they are executed. This queue will hold only the Runnable tasks submitted by the execute method.)

  handler : 对拒绝任务的处理策略(the handler to use when execution is blocked because the thread bounds and queue capacities are reached.)

 

  经过上面的构造函数,能够构造一个线程池对象threadPool。在Java中,一个任务就是一个Runnable类的对象,具体的业务处理逻辑在该对象的run()方法中实现。经过threadPoool.execute(Runnable)方法,任务被提交到了线程池中并执行。

  【代码实例】

  任务类:

 1 package com.code.threadpool;
 2 
 3 import java.io.Serializable;
 4 
 5 public class ThreadPoolTask implements Runnable, Serializable {
 6 
 7     private static final long serialVersionUID = 1L;
 8 
 9     private Object threadPoolTaskData;
10 
11     ThreadPoolTask(Object tasks) {
12         this.threadPoolTaskData = tasks;
13     }
14 
15     public void run() {
16         System.out.println("start ..." + threadPoolTaskData);
17         try {
18             Thread.sleep(2000);
19         } catch (Exception e) {
20             e.printStackTrace();
21         }
22         System.out.println("end ..." + threadPoolTaskData);
23         threadPoolTaskData = null;
24     }
25 
26 }

线程池测试类:

 1 package com.code.threadpool;
 2 
 3 import java.util.concurrent.ArrayBlockingQueue;
 4 import java.util.concurrent.ThreadPoolExecutor;
 5 import java.util.concurrent.TimeUnit;
 6 
 7 public class ThreadPoolTest {
 8 
 9     /**
10      * 核心线程数量,线程池维护线程的最少数量
11      */
12     private static final int corePoolSize = 2;
13 
14     /**
15      * 线程池维护线程的最大数量
16      */
17     private static final int maxPoolSize = 4;
18 
19     /**
20      * 线程池维护线程所容许的空闲时间
21      */
22     private static final int keepAliveTime = 3;
23 
24     /**
25      * 线程池所使用的缓冲队列的大小
26      */
27     private static final int workQueueSize = 3;
28 
29     /**
30      * 线程执行任务后sleep的时间,sleep是为了便于观察程序的运行结果
31      */
32     private static final int produceTaskSleepTime = 2;
33 
34     /**
35      * 任务的最大数量
36      */
37     private static final int produceTaskMaxNumber = 10;
38 
39     /**
40      * 任务名称的前缀
41      */
42     private static final String taskNamePrefix = "task@";
43 
44     public static void main(String[] args) {
45 
46         ThreadPoolExecutor threadPool = new ThreadPoolExecutor(corePoolSize,
47                 maxPoolSize, keepAliveTime, TimeUnit.SECONDS,
48                 new ArrayBlockingQueue<Runnable>(workQueueSize),
49                 new ThreadPoolExecutor.DiscardOldestPolicy());
50 
51         for (int i = 0; i < produceTaskMaxNumber; i++) {
52             String taskName = taskNamePrefix + (i + 1);
53             System.out.println(String.format("put %s", taskName));
54 
55             System.out.println("--- before put " + taskName
56                     + ", active thread count: " + threadPool.getActiveCount());
57             ThreadPoolTask task = new ThreadPoolTask(taskName);
58             threadPool.execute(task);
59             System.out.println("--- after put " + taskName
60                     + ", active thread count: " + threadPool.getActiveCount());
61 
62             try {
63                 Thread.sleep(produceTaskSleepTime);
64             } catch (InterruptedException e) {
65                 e.printStackTrace();
66             }
67         }
68     }
69 
70 }

【运行结果】

 1 put task@1
 2 --- before put task@1, active thread count: 0
 3 --- after put task@1, active thread count: 0
 4 start ...task@1
 5 put task@2
 6 --- before put task@2, active thread count: 1
 7 --- after put task@2, active thread count: 1
 8 start ...task@2
 9 put task@3
10 --- before put task@3, active thread count: 2
11 --- after put task@3, active thread count: 2
12 put task@4
13 --- before put task@4, active thread count: 2
14 --- after put task@4, active thread count: 2
15 put task@5
16 --- before put task@5, active thread count: 2
17 --- after put task@5, active thread count: 2
18 put task@6
19 --- before put task@6, active thread count: 2
20 --- after put task@6, active thread count: 2
21 start ...task@6
22 put task@7
23 --- before put task@7, active thread count: 3
24 --- after put task@7, active thread count: 3
25 start ...task@7
26 put task@8
27 --- before put task@8, active thread count: 4
28 --- after put task@8, active thread count: 4
29 put task@9
30 --- before put task@9, active thread count: 4
31 --- after put task@9, active thread count: 4
32 put task@10
33 --- before put task@10, active thread count: 4
34 --- after put task@10, active thread count: 4
35 end ...task@1
36 start ...task@8
37 end ...task@2
38 start ...task@9
39 end ...task@6
40 start ...task@10
41 end ...task@7
42 end ...task@8
43 end ...task@9
44 end ...task@10

 

参考资料:

  一、http://blog.itpub.net/9399028/viewspace-1852029/

  二、http://blog.csdn.net/newchenxf/article/details/51996950

  三、http://uule.iteye.com/blog/1123185

  四、http://www.cnblogs.com/dolphin0520/p/3932921.html

  五、https://segmentfault.com/a/1190000007120459

 

本文为原创文章,转载请注明出处:http://www.cnblogs.com/acode/p/6385880.html

相关文章
相关标签/搜索