首先,让我们问一个问题,为什么要使用线程池?很多时候,我们使用多线程来执行任务的时候都是这样一个场景:每新建一个任务就对应地创建一个线程,而往往每个任务在很短的时间内就结束了,导致线程的创建和销毁频繁发生,这会降低系统的效率。线程池的应用便应运而生。

一,Java线程池

1,ThreadPoolExecutor

ThreadPoolExecutor是线程池任务执行器。其继承链为

ThreadPoolExecutor extends AbstractExecutorService implements ExecutorServiceextendsExecutor

ThreadPoolExecutor的几个重要构造参数包括以下:

1)corePoolSize:核心池尺寸,当池大小小于corePoolSize时,就新建线程来执行任务。当池大小等于corePoolSize时,就将任务放进workQueue阻塞队列。池子中的空闲线程去队列中获取任务来执行。

2)maximumPoolSize:最大池尺寸,当队列已经满了,就新建线程入池来处理请求,但是线程数量不能超过最大池尺寸。

3)keepAliveTime:线程存活时间,决定当一个线程空闲了多长时间后被销毁。只有在线程池尺寸大于corePoolSize时才起作用。

4)unit:时间单位,有7种选择:

TimeUnit.DAYS;              //天

TimeUnit.HOURS;            //小时

TimeUnit.MINUTES;          //分钟

TimeUnit.SECONDS;          //秒

TimeUnit.MILLISECONDS;     //毫秒

TimeUnit.MICROSECONDS;     //微妙

TimeUnit.NANOSECONDS;     //纳秒

5)workQueue:阻塞队列,用来存储待执行的任务。声明类型为BlockingQueue<Runnable>,有以下几种选择:

ArrayBlockingQueue

基于数组,先进先出,必须指定大小

LinkedBlockingQueue

基于链表,先进先出,如未指定大小,则为Integer.MAX_VALUE

SynchronousQueue

没有尺寸的概念,不会保存提交的任务,而是将直接新建一个线程来执行新来的任务

PriorityBlockingQueue

其存储的对象必须实现Comparable接口,队列根据compare接口方法确定任务的优先级

常用的是LinkedBlockingQueue和SynchronousQueue

6)threadFactory,线程工厂,用来创建线程。

7)handler,拒绝处理任务时的策略,包括

ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常。

ThreadPoolExecutor.DiscardPolicy:丢弃任务,不抛出异常。

ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程)

ThreadPoolExecutor.CallerRunsPolicy:由调用线程处理该任务

ThreadPoolExecutor的几个重要方法

1)execute()

向线程池提交任务,交由线程池来执行

2)submit()

同样是向线程池提交任务,其内部调用了execute(),区别是,会返回一个FutureTask实例

3)shutdown()

等任务都执行完毕后关闭线程池,并且拒绝接受新的任务

4)shutdownNow()

停止正在执行的任务,立刻关闭线程池,拒绝接受新的任务

5)isTerminated()

检查线程池是否已关闭

代码示例:

任务类

package com.wxy.popcorn.threadpool;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;public class Task implements Runnable {private Logger logger = LoggerFactory.getLogger(getClass());private String tName;public Task(String tName) {this.tName = tName;}public void run() {logger.info("{} is executing the {}", Thread.currentThread().getName(), tName);}
}

任务执行器

package com.wxy.popcorn.threadpool;import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;public class TaskExecutor {private Logger logger = LoggerFactory.getLogger(getClass());private int executeTimes;private ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(4, 10, 2000L,TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(100), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());public TaskExecutor(int executeTimes) {this.executeTimes = executeTimes;}public void executeTasks() {for (int i=0; i< executeTimes; i++) {threadPoolExecutor.execute(new Task("task"+i));}threadPoolExecutor.shutdown();while (true) {if (threadPoolExecutor.isTerminated()) {logger.info("==========End to execute the tasks==========");break;}}}
}

测试类

package com.wxy.popcorn.threadpool;import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;public class TaskExecutorTest {private Logger logger = LoggerFactory.getLogger(getClass());@Testpublic void test() {logger.info("==========Begin to execute tasks==========");new TaskExecutor(20).executeTasks();}
}

测试结果

2017-12-25 23:15:28.735 [main] INFO  [TaskExecutorTest.java:12] ==========Begin to execute tasks==========
2017-12-25 23:15:28.753 [pool-2-thread-3] INFO  [Task.java:15] pool-2-thread-3 is executing the task2
2017-12-25 23:15:28.753 [pool-2-thread-1] INFO  [Task.java:15] pool-2-thread-1 is executing the task0
2017-12-25 23:15:28.753 [pool-2-thread-2] INFO  [Task.java:15] pool-2-thread-2 is executing the task1
2017-12-25 23:15:28.756 [pool-2-thread-3] INFO  [Task.java:15] pool-2-thread-3 is executing the task4
2017-12-25 23:15:28.756 [pool-2-thread-1] INFO  [Task.java:15] pool-2-thread-1 is executing the task5
2017-12-25 23:15:28.756 [pool-2-thread-4] INFO  [Task.java:15] pool-2-thread-4 is executing the task3
2017-12-25 23:15:28.756 [pool-2-thread-2] INFO  [Task.java:15] pool-2-thread-2 is executing the task6
2017-12-25 23:15:28.756 [pool-2-thread-3] INFO  [Task.java:15] pool-2-thread-3 is executing the task7
2017-12-25 23:15:28.757 [pool-2-thread-1] INFO  [Task.java:15] pool-2-thread-1 is executing the task8
2017-12-25 23:15:28.757 [pool-2-thread-4] INFO  [Task.java:15] pool-2-thread-4 is executing the task9
2017-12-25 23:15:28.757 [pool-2-thread-2] INFO  [Task.java:15] pool-2-thread-2 is executing the task10
2017-12-25 23:15:28.757 [pool-2-thread-3] INFO  [Task.java:15] pool-2-thread-3 is executing the task11
2017-12-25 23:15:28.757 [pool-2-thread-1] INFO  [Task.java:15] pool-2-thread-1 is executing the task12
2017-12-25 23:15:28.757 [pool-2-thread-4] INFO  [Task.java:15] pool-2-thread-4 is executing the task13
2017-12-25 23:15:28.757 [pool-2-thread-2] INFO  [Task.java:15] pool-2-thread-2 is executing the task14
2017-12-25 23:15:28.757 [pool-2-thread-3] INFO  [Task.java:15] pool-2-thread-3 is executing the task15
2017-12-25 23:15:28.757 [pool-2-thread-1] INFO  [Task.java:15] pool-2-thread-1 is executing the task16
2017-12-25 23:15:28.757 [pool-2-thread-4] INFO  [Task.java:15] pool-2-thread-4 is executing the task17
2017-12-25 23:15:28.757 [pool-2-thread-2] INFO  [Task.java:15] pool-2-thread-2 is executing the task18
2017-12-25 23:15:28.758 [pool-2-thread-3] INFO  [Task.java:15] pool-2-thread-3 is executing the task19
2017-12-25 23:15:28.758 [main] INFO  [TaskExecutor.java:28] ==========End to execute the tasks==========

2,其它Java线程池

除了ThreadPoolExecutor,jdk还提供了其它多种线程池。通过Executors类的成员方法来生成实例。

1)newCachedThreadPool

public static ExecutorService newCachedThreadPool() {return new ThreadPoolExecutor(0, Integer.MAX_VALUE,60L, TimeUnit.SECONDS,new SynchronousQueue<Runnable>());}

2)newFixedThreadPool

public static ExecutorService newFixedThreadPool(intnThreads){return new ThreadPoolExecutor(nThreads,nThreads,0L,TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>());}

3)newScheduledThreadPool,创建一个无尺寸上限的线程池,支持定时和周期性任务。

public static ScheduledExecutorService newScheduledThreadPool(intcorePoolSize){return new ScheduledThreadPoolExecutor(corePoolSize);}

4)newSingleThreadExecutor,只会使用唯一的线程来执行任务,保证所有的任务都按照指定顺序执行。

public static ExecutorService newSingleThreadExecutor(){return new FinalizableDelegatedExecutorService(new ThreadPoolExecutor(1,1,0L,TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>()));}

二,spring线程池

ThreadPoolTaskExecutor是spring提供的线程池。其使用与Java线程池类似,不做赘述。直接查看示例代码。这里使用spring-boot的方式来进行配置。

任务类:

package com.wxy.popcorn.springthreadpool;import java.util.concurrent.CountDownLatch;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;public class SpringTask implements Runnable{private Logger logger = LoggerFactory.getLogger(getClass());private String tName;private CountDownLatch endGate;public SpringTask(String tName) {this.tName = tName;}public void run() {logger.info("{} is executing the {}", Thread.currentThread().getName(), tName);}
}

配置类

package com.wxy.popcorn.springthreadpool;import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;@Configuration
@PropertySource("classpath:threadpool.properties")
public class SpringConfig {@Bean@ConfigurationProperties(prefix = "thread.pool")public ThreadPoolTaskExecutor taskExecutor() {return new ThreadPoolTaskExecutor();}
}

属性文件

#线程池
#线程池维护线程的最少数量
thread.pool.core-pool-size=10
#线程池维护线程的最大数量
thread.pool.max-pool-size=20
#缓存队列
thread.pool.queue-capacity=100
#允许的空闲时间
thread.pool.keep-alive-seconds=300

启动类

package com.wxy.popcorn.springthreadpool;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class SpringApp {public static void main(String[] args) {SpringApplication.run(SpringApp.class, args);}
}

测试类

package com.wxy.popcorn.springthreadpool;import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.test.context.junit4.SpringRunner;@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringTaskExecutorTest {@AutowiredThreadPoolTaskExecutor threadPoolTaskExecutor;@Testpublic void test() {for (int i=0; i< 20; i++) {threadPoolTaskExecutor.execute(new SpringTask("task"+i));}}
}

测试结果

2017-12-25 23:08:59.215 [taskExecutor-2] INFO  [SpringTask.java:18] taskExecutor-2 is executing the task1
2017-12-25 23:08:59.215 [taskExecutor-5] INFO  [SpringTask.java:18] taskExecutor-5 is executing the task4
2017-12-25 23:08:59.215 [taskExecutor-9] INFO  [SpringTask.java:18] taskExecutor-9 is executing the task8
2017-12-25 23:08:59.216 [taskExecutor-4] INFO  [SpringTask.java:18] taskExecutor-4 is executing the task3
2017-12-25 23:08:59.216 [taskExecutor-3] INFO  [SpringTask.java:18] taskExecutor-3 is executing the task2
2017-12-25 23:08:59.215 [taskExecutor-1] INFO  [SpringTask.java:18] taskExecutor-1 is executing the task0
2017-12-25 23:08:59.215 [taskExecutor-7] INFO  [SpringTask.java:18] taskExecutor-7 is executing the task6
2017-12-25 23:08:59.215 [taskExecutor-6] INFO  [SpringTask.java:18] taskExecutor-6 is executing the task5
2017-12-25 23:08:59.215 [taskExecutor-8] INFO  [SpringTask.java:18] taskExecutor-8 is executing the task7
2017-12-25 23:08:59.216 [taskExecutor-10] INFO  [SpringTask.java:18] taskExecutor-10 is executing the task9
2017-12-25 23:08:59.224 [taskExecutor-2] INFO  [SpringTask.java:18] taskExecutor-2 is executing the task10
2017-12-25 23:08:59.224 [taskExecutor-5] INFO  [SpringTask.java:18] taskExecutor-5 is executing the task11
2017-12-25 23:08:59.224 [taskExecutor-9] INFO  [SpringTask.java:18] taskExecutor-9 is executing the task12
2017-12-25 23:08:59.224 [taskExecutor-4] INFO  [SpringTask.java:18] taskExecutor-4 is executing the task13
2017-12-25 23:08:59.224 [taskExecutor-3] INFO  [SpringTask.java:18] taskExecutor-3 is executing the task14
2017-12-25 23:08:59.224 [taskExecutor-1] INFO  [SpringTask.java:18] taskExecutor-1 is executing the task15
2017-12-25 23:08:59.225 [taskExecutor-7] INFO  [SpringTask.java:18] taskExecutor-7 is executing the task16
2017-12-25 23:08:59.225 [taskExecutor-6] INFO  [SpringTask.java:18] taskExecutor-6 is executing the task17
2017-12-25 23:08:59.225 [taskExecutor-8] INFO  [SpringTask.java:18] taskExecutor-8 is executing the task18
2017-12-25 23:08:59.225 [taskExecutor-10] INFO  [SpringTask.java:18] taskExecutor-10 is executing the task19

基于线程池实现多线程任务相关推荐

  1. linux线程池实现多线程并发,基于Linux的多线程池并发Web服务器设计-电子设计工程.PDF...

    基于Linux的多线程池并发Web服务器设计-电子设计工程.PDF 第 卷 第 期 电子设计工程 年 月 基于 的多线程池并发 服务器设计 陈 涛 任海兰 武汉邮电科学研究院 湖北 武汉 摘要 时至今 ...

  2. 高性能dhcp服务器,基于线程池机制的高性能DHCP服务器研究与实现

    摘要: 随着互联网的蓬勃发展,IP地址资源越来越紧张.DHCP服务是在现有IPv4协议基础上解决IP地址资源短缺问题的有效途径. 目前,多数DHCP服务器是单线程运行,串行处理客户请求的.其应用于大型 ...

  3. dhcp计算机毕业论文,基于线程池机制的高性能DHCP服务器研究与实现-计算机科学与技术专业毕业论文.docx...

    文档介绍: 西北丁业大学硕士学位论文 摘要摘 要随着互联网的蓬勃发展,IP地址资源越来越紧张.DHCP服务是在现有IPv4协议基础上解决IP地址资源短缺问题的有效途径.目前,多数DHCP服务器是单线程 ...

  4. java中定时任务和线程池_java基于线程池和反射机制实现定时任务完整实例

    本文实例讲述了java基于线程池和反射机制实现定时任务的方法.分享给大家供大家参考,具体如下: 主要包括如下实现类: 1. Main类: 任务执行的入口: 调用main方法,开始加载任务配置并执行任务 ...

  5. 【二十四】springboot使用EasyExcel和线程池实现多线程导入Excel数据

      springboot篇章整体栏目:  [一]springboot整合swagger(超详细 [二]springboot整合swagger(自定义)(超详细) [三]springboot整合toke ...

  6. Spring Boot 配置线程池使用多线程插入数据

    点击上方 好好学java ,选择 星标 公众号 重磅资讯.干货,第一时间送达 今日推荐:牛人 20000 字的 Spring Cloud 总结,太硬核了~个人原创+1博客:点击前往,查看更多 来源:h ...

  7. java线程池_Java多线程并发:线程基本方法+线程池原理+阻塞队列原理技术分享...

    线程基本方法有哪些? 线程相关的基本方法有 wait,notify,notifyAll,sleep,join,yield 等. 线程等待(wait) 调用该方法的线程进入 WAITING 状态,只有等 ...

  8. linux posix 线程池_linux多线程--POSIX Threads Programming

    linux多线程自己从接触很久也有不少实践,但总是觉得理解不够深刻,不够系统.借这篇文章试着再次系统学习一下linux多线程编程,理解编程的concept,细致看一下POSIX pthread API ...

  9. java多线程抽奖_java 线程池、多线程并发实战(生产者消费者模型 1 vs 10) 附案例源码...

    导读 前二天写了一篇<Java 多线程并发编程>点我直达,放国庆,在家闲着没事,继续写剩下的东西,开干! 线程池 为什么要使用线程池 例如web服务器.数据库服务器.文件服务器或邮件服务器 ...

  10. java 多线程使用线程池_Java多线程:如何开始使用线程

    java 多线程使用线程池 什么是线程? (What is a Thread?) A thread is a lightweight process. Any process can have mul ...

最新文章

  1. 斯坦福的人工智能4年路线!
  2. AI来编程,码农何去何从?
  3. 20个必不可少的Python库
  4. php面向对象(OOP)---- 验证码类
  5. css设置背景图片缩小,css3 设置背景图片大小(缩略图形式缩小)
  6. 物料分类账的基本原理
  7. 十个模块_专栏 | ABAQUS Part模块的十个小技巧
  8. 安卓学习笔记38:利用OpenGL ES绘制旋转立方体
  9. html5 成语连连看,全国通用五年级下册语文讲义-阅读与作文:学写读后感(含答案)[参考].pdf...
  10. NAS网络存储使用教程之如何新建用户
  11. copy的过去式_[copy是什么意思中文翻译成]copy是什么意思中文翻译
  12. 腾讯云函数转华为云函数
  13. 计算机运行一段时间假死,电脑使用一段时间后变慢或死机(提高电脑运行速度技巧)...
  14. oracle dbf 超大,system01.dbf文件过大——SYSTEM表空间AUD$使用空间过大问题处理
  15. runtime error python怎么解决_RuntimeError: Python is not installed as a framework 错误解决方案...
  16. 欢迎下载psp的埃舍尔画集主题
  17. Postman知识汇总
  18. 销售宝:如何选择财务软件?财务软件哪个好?
  19. 华为od机考真题-数组拼接
  20. 【前端入门】JavaScript(3)

热门文章

  1. 电脑术语中:directory 和 folder 的区别
  2. 几张图轻松理解String.intern()
  3. 还在用git commit -m 吗?Git 提交规范和自动产生changelog手摸手教程。
  4. 2021个人年度总结-追寻
  5. “任务管理器已被管理员禁用”如何解除?
  6. 栅栏CyclicBarrier
  7. SC0084 AT32F407/437在UCOSIII上运行LwIP协议栈
  8. drain open 线与_Open-Drain与Push-Pull
  9. 什么是监控报警以及如何实现
  10. 谷歌中国四年去本地化接近尾声