博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
2018-06-14: Java 定时任务线程池 ExecutorService 使用总结
阅读量:7201 次
发布时间:2019-06-29

本文共 6263 字,大约阅读时间需要 20 分钟。

1、背景:

重构了一个项目,将以前散乱的多线程和定时任务线程做统一管理,减少代码量并提升代码可读性。

2、直接上代码 - 可直接COPY使用 ----------------------------

-、新建一个线程池构造工厂类 ExecutorServiceFactory:

package com.aaa.bbb.ccc.ddd;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.ThreadFactory;import java.util.concurrent.atomic.AtomicInteger;/*** @Function : 线程池构造工厂* @Author & @Date : lynn_ - 2018年6月14日*/public class ExecutorServiceFactory {// 实例化ExecutorServiceFactoryprivate static ExecutorServiceFactory executorServiceFactory = new ExecutorServiceFactory();// 定时任务线程池private ExecutorService executorService;/** * 默认无参构造 */private ExecutorServiceFactory() { }/** * @Function: 获取ExecutorServiceFactory */public static ExecutorServiceFactory getInstance() {	return executorServiceFactory;}/** * @Function: 创建一个定长的线程池 - 它可安排在给定延迟后运行命令或者定期地执行 */public ExecutorService createScheduledThreadPool() {	// CPU个数	int availableProcessors = Runtime.getRuntime().availableProcessors();	// 创建	executorService = Executors.newScheduledThreadPool(availableProcessors * 10, getThreadFactory());	return executorService;}/** * @Function: 创建一个单线程化的Executor,即只创建唯一的工作者线程来执行任务,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行 *            Executor,以无界队列方式来运行该线程。(注意,如果因为在关闭前的执行期间出现失败而终止了此单个线程, *            那么如果需要,一个新线程将代替它执行后续的任务 )。可保证顺序地执行各个任务, *            并且在任意给定的时间不会有多个线程是活动的。与其他等效的 newFixedThreadPool(1) *            不同,可保证无需重新配置此方法所返回的执行程序即可使用其他的线程。 */public ExecutorService createSingleThreadExecutor() {	// 创建	executorService = Executors.newSingleThreadExecutor(getThreadFactory());	return executorService;}/** * @Function: 创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程 *            对于执行很多短期异步任务的程序而言,这些线程池通常可提高程序性能。调用 execute将重用以前构造的线程(如果线程可用)。 *            如果现有线程没有可用的,则创建一个新线程并添加到池中。 终止并从缓存中移除那些已有 60 秒钟未被使用的线程。 *            因此,长时间保持空闲的线程池不会使用任何资源。注意,可以使用 ThreadPoolExecutor *            构造方法创建具有类似属性但细节不同(例如超时参数)的线程池。 */public ExecutorService createCachedThreadPool() {	// 创建	executorService = Executors.newCachedThreadPool(getThreadFactory());	return executorService;}/** * @Function: 创建一个指定工作线程数量的线程池。每当提交一个任务就创建一个工作线程, *            如果工作线程数量达到线程池初始的最大数,则将提交的任务存入到池队列中。 *            可重用固定线程数的线程池,以共享的无界队列方式来运行这些线程。在任意点,在大多数 nThreads *            线程会处于处理任务的活动状态。如果在所有线程处于活动状态时提交附加任务,则在有可用线程之前,附加任务将在队列中等待。 *            如果在关闭前的执行期间由于失败而导致任何线程终止,那么一个新线程将代替它执行后续的任务(如果需要)。 *            在某个线程被显式地关闭之前,池中的线程将一直存在。 */public ExecutorService createFixedThreadPool(int count) {	// 创建	executorService = Executors.newFixedThreadPool(count, getThreadFactory());	return executorService;}/** * @Function: 获取线程池工厂 */private ThreadFactory getThreadFactory() {    return new ThreadFactory() {        // AtomicInteger是一个提供原子操作的Integer类,通过线程安全的方式操作加减        AtomicInteger sn = new AtomicInteger();    	@Override    	public Thread newThread(Runnable r) {    		// 安全管理器    		SecurityManager s = System.getSecurityManager();    		// 所有线程都隶属于一个线程组    		ThreadGroup group = (s != null) ? s.getThreadGroup() : Thread.currentThread().getThreadGroup();    		Thread t = new Thread(group, r);    		t.setName("任务线程 - " + sn.incrementAndGet());    		return t;    	}	};}}复制代码

--、新建一个线程处理类 ExecutorProcessPool:

package com.aaa.bbb.ccc.ddd;import java.util.concurrent.Callable;import java.util.concurrent.ExecutorService;import java.util.concurrent.Future;/** * @Function :  线程处理类* @Author & @Date : lin.li  - 2018年6月14日 */ public class ExecutorProcessPool {//线程池接口private ExecutorService executor;//实例化当前类private static ExecutorProcessPool pool = new ExecutorProcessPool();/** * Creates a new instance of ExecutorProcessPool */private ExecutorProcessPool() {    executor = ExecutorServiceFactory.getInstance().createCachedThreadPool();}/** * @Function: 获取 ExecutorProcessPool */public static ExecutorProcessPool getInstance() {    return pool;}/** * @Function:  关闭线程池,这里要说明的是:调用关闭线程池方法后,线程池会执行完队列中的所有任务才退出 */public void shutdown(){    executor.shutdown();}/** * @Function: 提交任务到线程池,可以接收线程返回值 - Future模式 */public Future
submit(Runnable task) { return executor.submit(task);}public Future
submit(Callable
task) { return executor.submit(task);}/** * @Function: 直接提交任务到线程池,无返回值 */public void execute(Runnable task){ executor.execute(task);}}复制代码

---、核心代码就这点了,下面是测试类 ExecutorTest:

package com.goldpac.ito.system.interceptor;import java.util.concurrent.Callable;import java.util.concurrent.Future;import java.util.concurrent.TimeUnit;/*** @Function : 线程池测试类* @Author & @Date : lin.li - 2018年6月11日*/public class ExecutorTest {public static void main(String[] args) {    //获取实例    ExecutorProcessPool pool = ExecutorProcessPool.getInstance();    //for循环添加多个线程 -     for (int i = 0; i < 200; i++) {        Future
future = pool.submit(new ExcuteTask1(i + "")); try { //如果接收线程返回值,future.get() 会阻塞,如果这样写就是一个线程一个线程执行。所以非特殊情况不建议使用接收返回值的。 System.out.println(future.get()); } catch (Exception e) { e.printStackTrace(); } } //没有返回值。可以执行任务,但无法判断任务是否成功完成。 //execute(Runnable x); //for (int i = 0; i < 200; i++) { // pool.execute(new ExcuteTask2(i + "")); //} // 关闭线程池,如果是需要长期运行的线程池,不用调用该方法。 // 监听程序退出的时候最好执行一下。 pool.shutdown();}/** * 执行任务1,实现Callable方式 */static class ExcuteTask1 implements Callable
{ private String taskName; public ExcuteTask1(String taskName) { this.taskName = taskName; } @Override public String call() throws Exception { try { // Java 6/7最佳的休眠方法为TimeUnit.MILLISECONDS.sleep(100); // 最好不要用 Thread.sleep(100); // 1000毫秒以内的随机数,模拟业务逻辑处理 TimeUnit.MILLISECONDS.sleep((int) (Math.random() * 1000)); } catch (Exception e) { e.printStackTrace(); } System.out.println("-------------这里执行业务逻辑,Callable TaskName = " + taskName + "-------------"); return ">>>>>>>>>>>>>线程返回值,Callable TaskName = " + taskName + "<<<<<<<<<<<<<<"; }}/** * 执行任务2,实现Runable方式 */static class ExcuteTask2 implements Runnable { private String taskName; public ExcuteTask2(String taskName) { this.taskName = taskName; } @Override public void run() { try { // 1000毫秒以内的随机数,模拟业务逻辑处理 TimeUnit.MILLISECONDS.sleep((int) (Math.random() * 1000)); } catch (Exception e) { e.printStackTrace(); } System.out.println("-------------这里执行业务逻辑,Runnable TaskName = " + taskName + "-------------"); }}}复制代码

转载地址:http://klcum.baihongyu.com/

你可能感兴趣的文章
代理服务器与网络地址转换NAT
查看>>
nginx学习笔记
查看>>
OSChina 双十一乱弹 ——来自单身狗的哀鸣
查看>>
Maven: Usage
查看>>
CF991C Candies 二分 第十五
查看>>
查找两个有序数组中的第K个元素(find kth smallest element in 2 sorted arrays)
查看>>
sqlmap注入之tamper绕过WAF防火墙过滤
查看>>
如何用Tacker将NFV带入OpenStack?
查看>>
快速排序简明教程
查看>>
【转】Unity3D学习日记(二)使用UGUI制作虚拟摇杆控制摄像机
查看>>
【BZOJ3110】【Zjoi2013】K大数查询 - 2
查看>>
zabbix安装源
查看>>
java例程练习(多线程的两种创建方式)
查看>>
随题而学(二)多维数组转一维数组
查看>>
创建Dynamic Web Project工程
查看>>
Confirm the Ending
查看>>
day5 python全栈学习笔记
查看>>
ntp网络时间服务搭建
查看>>
php 正则 常用基础
查看>>
iview给radio按钮组件加点击事件
查看>>