├── 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