├── README.md
├── src
└── main
│ ├── assembly
│ └── local.properties
│ ├── java
│ └── com
│ │ └── jp
│ │ └── nian
│ │ └── threadpool
│ │ └── core
│ │ ├── Pool.java
│ │ ├── TestMain.java
│ │ ├── Task.java
│ │ ├── PoolThread.java
│ │ └── ThreadPool.java
│ └── resources
│ └── log4j.xml
└── pom.xml
/README.md:
--------------------------------------------------------------------------------
1 | # threadpool-core
2 | java 实现线程池
3 |
--------------------------------------------------------------------------------
/src/main/assembly/local.properties:
--------------------------------------------------------------------------------
1 | #log4j
2 | log4j.log.level=INFO
3 | log4j.log.console=
4 |
--------------------------------------------------------------------------------
/src/main/java/com/jp/nian/threadpool/core/Pool.java:
--------------------------------------------------------------------------------
1 | package com.jp.nian.threadpool.core;
2 | /**
3 | * @ClassName: Pool
4 | * @Description: 线程池接口
5 | * @date: 2017年1月11日 上午11:43:06
6 | *
7 | * @author tanfan
8 | * @version @param
9 | * @since JDK 1.7
10 | */
11 | public interface Pool {
12 | //关闭线程池,会等待未完成任务的线程
13 | void shutdown();
14 | //立即关闭线程池,不会等待线程完成
15 | void shutdownnow();
16 | //执行任务
17 | void execute(Task task);
18 | //借
19 | T borrowFromPool();
20 | //还
21 | void returnToPool(T t);
22 | //得到线程池关闭标志
23 | public boolean isShutdown();
24 | //设置线程池关闭标志
25 | public void setShutdown(boolean isShutdown) ;
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/src/main/resources/log4j.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | ${log4j.log.console}
16 |
17 |
18 |
19 |
20 | ${log4j.log.console}
21 |
22 |
23 |
--------------------------------------------------------------------------------
/src/main/java/com/jp/nian/threadpool/core/TestMain.java:
--------------------------------------------------------------------------------
1 | package com.jp.nian.threadpool.core;
2 |
3 | import org.slf4j.Logger;
4 | import org.slf4j.LoggerFactory;
5 |
6 | /**
7 | * @ClassName: TestMain
8 | * @Description: 测试多线程池类
9 | * @date: 2017年1月11日 上午11:42:26
10 | *
11 | * @author tanfan
12 | * @version
13 | * @since JDK 1.7
14 | */
15 | public class TestMain {
16 | private static final Logger logger = LoggerFactory.getLogger(TestMain.class);
17 | public static void main(String[] args) {
18 | logger.info("start....");
19 | //初始化10个线程,默认5个初始化线程
20 | Pool pool = new ThreadPool(10);
21 | //初始化100个任务
22 | Task[] task = new Task[100];
23 | for(int i=0;i < task.length;i++){
24 | task[i] = new Task("name"+i);
25 | //10个线程去执行100个任务,肯定有线程执行2个或2个以上的任务
26 | pool.execute(task[i]);
27 | }
28 | //等待任务运行完执行
29 | pool.shutdown();
30 | logger.info("线程池关闭....");
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/main/java/com/jp/nian/threadpool/core/Task.java:
--------------------------------------------------------------------------------
1 | package com.jp.nian.threadpool.core;
2 |
3 | import java.util.concurrent.TimeUnit;
4 |
5 | import org.slf4j.Logger;
6 | import org.slf4j.LoggerFactory;
7 |
8 | /**
9 | * @ClassName: Task
10 | * @Description: 模拟的任务
11 | * @date: 2017年1月11日 上午11:43:37
12 | *
13 | * @author tanfan
14 | * @version
15 | * @since JDK 1.7
16 | */
17 | public class Task {
18 | private static final Logger logger = LoggerFactory.getLogger(Task.class);
19 | private String name;
20 |
21 | public Task(String name) {
22 | this.name = name;
23 | }
24 |
25 | @Override
26 | public String toString() {
27 | return "Task[name="+name+"]";
28 | }
29 |
30 | public void doSomething() {
31 | long sleepTime = new Double(Math.random()*10).longValue();
32 | try {
33 | //模拟任务的执行时间
34 | logger.info("{} doing my task|{}, I need execute {} s", new Object[]{Thread.currentThread().getName(), this, sleepTime});
35 | TimeUnit.SECONDS.sleep(sleepTime);
36 | } catch (InterruptedException e) {
37 | logger.error("{} execute task|{} error",new Object[]{Thread.currentThread().getName(), this, e});
38 | }
39 | logger.info("{} done my task|{}", Thread.currentThread().getName(), this);
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/main/java/com/jp/nian/threadpool/core/PoolThread.java:
--------------------------------------------------------------------------------
1 | package com.jp.nian.threadpool.core;
2 |
3 | import org.apache.commons.lang3.builder.ToStringBuilder;
4 | import org.apache.commons.lang3.builder.ToStringStyle;
5 | import org.slf4j.Logger;
6 | import org.slf4j.LoggerFactory;
7 |
8 | /**
9 | * @ClassName: PoolThread
10 | * @Description: 线程池中的线程
11 | * 工作者线程与通常线程不同之处在于run()方法的不同。通常的线程,
12 | 完成线程应该执行的代码后,自然退出,线程结束。
13 | 虚拟机在线程结束后收回分配给线程的资源,线程对象被垃圾回收。]
14 | 而这在池化的工作者线程中是应该避免的,否则线程池就失去了意义。
15 | 作为可以被放入池中并重新利用的工作者线程,它的run()方法不应该结束,
16 | 随意,在随后可以看到的实现中,run()方法执行完任务后,
17 | 就将回收到池中,然后调用wait()方法,使自己等待而不是退出循环和run()。
18 | 这就使线程池实现的要点。
19 | * @date: 2016年10月8日 下午2:23:07
20 | *
21 | * @author tanfan
22 | * @version
23 | * @since JDK 1.7
24 | */
25 | public class PoolThread extends Thread {
26 | //线程的任务
27 | private Task task;
28 | //线程所在的线程池
29 | private ThreadPool pool;
30 | private ThreadLocal idleLocal = new ThreadLocal(){
31 | protected Boolean initialValue(){
32 | return true;
33 | }
34 | };
35 |
36 | //日志组件
37 | private static final Logger logger = LoggerFactory.getLogger(PoolThread.class);
38 |
39 | public PoolThread(ThreadPool pool) {
40 | this.pool = pool;
41 | }
42 |
43 | @Override
44 | public void run() {
45 | while(idleLocal!=null && idleLocal.get()){
46 | logger.debug("{} my task is |{}", this.getName(), task);
47 | if(task!=null){
48 | try{
49 | idleLocal.set(false);
50 | logger.debug("{} will be execute task", this.getName());
51 | task.doSomething();
52 | synchronized (this) {
53 | //归还这个Thread
54 | pool.returnToPool(this);
55 | if(pool.isShutdown()){
56 | logger.debug("find thread pool shutdown, I am going die......");
57 | break;
58 | }
59 | logger.debug("{} do the work and will be wait", this.getName());
60 | this.wait();
61 | logger.debug("{} is notifyed by other ", this.getName());
62 | }
63 | if(idleLocal!=null){
64 | idleLocal.set(true);
65 | }
66 | }catch(Exception e){
67 | logger.error("thread|{} execute task error",this.getName(), e);
68 | }
69 | }
70 | }
71 | }
72 |
73 | public Task getTask() {
74 | return task;
75 | }
76 |
77 | public void setTask(Task task) {
78 | logger.debug("{} set the task|{} now ...",this.getName(), task);
79 | this.task = task;
80 | synchronized (this) {
81 | logger.debug("{} set the task synchronized ...", this.getName());
82 | this.notifyAll();
83 | }
84 | }
85 |
86 | public ThreadLocal getIdleLocal() {
87 | return idleLocal;
88 | }
89 |
90 | public void setIdleLocal(ThreadLocal idleLocal) {
91 | this.idleLocal = idleLocal;
92 | }
93 |
94 | public void close() {
95 | synchronized (this) {
96 | this.notifyAll();
97 | }
98 | }
99 |
100 | @Override
101 | public String toString() {
102 | return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
103 | }
104 | }
105 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
3 | 4.0.0
4 |
5 | com.jp.nian.threadpool
6 | threadpool-core
7 | 1.0.0-${dev.version.type}
8 | jar
9 |
10 | threadpool-core
11 | http://maven.apache.org
12 |
13 |
14 | UTF-8
15 | 1.6.6
16 | -SNAPSHOT
17 |
18 |
19 |
20 |
21 |
22 | org.slf4j
23 | slf4j-api
24 | ${org.slf4j-version}
25 |
26 |
27 | org.slf4j
28 | slf4j-log4j12
29 | ${org.slf4j-version}
30 |
31 |
32 | log4j
33 | log4j
34 | 1.2.15
35 |
36 |
37 | javax.mail
38 | mail
39 |
40 |
41 | javax.jms
42 | jms
43 |
44 |
45 | com.sun.jdmk
46 | jmxtools
47 |
48 |
49 | com.sun.jmx
50 | jmxri
51 |
52 |
53 |
54 |
55 | org.apache.commons
56 | commons-lang3
57 | 3.4
58 |
59 |
60 | junit
61 | junit
62 | 4.10
63 | test
64 |
65 |
66 |
67 |
68 |
69 |
70 | src/main/resources
71 | true
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 | local
80 |
81 | true
82 |
83 | env
84 | local
85 |
86 |
87 |
88 |
89 | src/main/assembly/local.properties
90 |
91 |
92 |
93 | ${dev.version.type}
94 | ${dev.version.type}
95 | ${dev.version.type}
96 |
97 |
98 |
99 | 自己实现一个线程池
100 |
101 |
--------------------------------------------------------------------------------
/src/main/java/com/jp/nian/threadpool/core/ThreadPool.java:
--------------------------------------------------------------------------------
1 | package com.jp.nian.threadpool.core;
2 |
3 | import java.util.HashSet;
4 | import java.util.Set;
5 | import java.util.concurrent.BlockingQueue;
6 | import java.util.concurrent.LinkedBlockingQueue;
7 | import java.util.concurrent.TimeUnit;
8 |
9 | import org.slf4j.Logger;
10 | import org.slf4j.LoggerFactory;
11 |
12 | /**
13 | * @ClassName: ThreadPool
14 | * @Description: 线程池
15 | * @date: 2016年10月8日 下午2:08:22
16 | *
17 | * @author tanfan
18 | * @version
19 | * @since JDK 1.7
20 | */
21 | public class ThreadPool implements Pool {
22 | //默认线程池的线程数
23 | private static final int DEFAULT_SIZE = 5;
24 | //线程池中的空闲线程,用队列表示
25 | private BlockingQueue idleThreads;
26 | //设置线程池是否关闭的标志
27 | private volatile boolean isShutdown = false;
28 | //存放所有线程池的所有线程,不管是否在执行任务
29 | private static Set threadSet = new HashSet<>();
30 | //日志组件
31 | private static final Logger logger = LoggerFactory.getLogger(ThreadPool.class);
32 |
33 | public ThreadPool(){
34 | this(DEFAULT_SIZE);
35 | }
36 |
37 | public ThreadPool(int threadSize){
38 | this.idleThreads = new LinkedBlockingQueue<>(threadSize);
39 | for(int i=0; i