线程管理之ExecutorService
2016-05-15 20:22
246 查看
转载请注明出处哦!
在Java 5之后,ExecutorService类被引入,主要是为了方便线程的统一管理。
每次创建新线程时,先检查自己的缓存池中有没有,没有才会创建。
它有默认的TimeOut(=60s),超过这个时长没活动的线程就会被自动的移除,所以完全不必要担心线程的结束问题。
这是比较推荐的类型。
- 它有线程数量上限。
- 它没有默认的TimeOut。
感觉并没有多大用处。
返回值为空,相当于没有返回值。
有返回值。
停止ExecutorService可以调用:
试想,当调用该方法后,每隔一会儿就有条新线程被创建,那么实际上这个线程池就永远关闭不了了。
并且当异常发生时,只能通过调用
下面是一个线程管理器的例子:
在Java 5之后,ExecutorService类被引入,主要是为了方便线程的统一管理。
ExecutorService的作用
ExecutorService其实是一个线程池,它可以接收任务,然后根据配置来分配线程,并控制其调度。分类
newCacheThreadPool
这种线程池是无界线程池,即它可以创建任意条线程。每次创建新线程时,先检查自己的缓存池中有没有,没有才会创建。
它有默认的TimeOut(=60s),超过这个时长没活动的线程就会被自动的移除,所以完全不必要担心线程的结束问题。
这是比较推荐的类型。
newFixedThreadPool
这个线程和newCacheThreadPool很类似,不同点在于:- 它有线程数量上限。
- 它没有默认的TimeOut。
ScheduledThreadPool
它可以按照顺序延迟调度线程。SingleThreadPool
它只有一条线程。感觉并没有多大用处。
ThreadPoolExecutor
这种类型的线程池可以自己配置相关参数。参数 | 说明 |
---|---|
corePoolSize | 池中所保存的线程数,包括空闲线程。 |
maximumPoolSize | 池中允许的最大线程数。’ |
keepAliveTime | 当线程数大于核心时,此为终止多余的空闲等待新任务的线程的最长时间。 |
workQueue | 执行前用于保持任务的队列。此队列仅保持由 execute 方法提交的 Runnable 任务。 |
启动任务的两种方法
execute()
启动任务,不能接收返回值。submit()
启动任务,并且能够接收返信息。任务分类
实现Runnable()接口
在run()方法中处理业务。
返回值为空,相当于没有返回值。
实现Callable()接口
在call()方法中处理业务。
有返回值。
关闭线程池的概念
关闭线程池指的是不再接收新任务,而不是停止线程的意思。停止ExecutorService可以调用:
shutDown()
这种方法要在池中所有线程执行完毕后才会关闭线程池,不再接收新的任务。试想,当调用该方法后,每隔一会儿就有条新线程被创建,那么实际上这个线程池就永远关闭不了了。
shutDownNow()
这是一种优雅的方式,它会立即关闭线程池,但是正在执行中的线程仍然可以执行完。Future
使用submit()添加任务,会返回一个
Future<?>对象,如果任务类型是
Callable<?>的话,它两的泛型是一样的。
并且当异常发生时,只能通过调用
Future.get()方法来抛出异常,否则异常将被线程池吃掉。
下面是一个线程管理器的例子:
import android.support.annotation.NonNull; import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; public class AppThreadManager { /** 线程管理器实例,为单例模式*/ public static volatile AppThreadManager Instance = null; /** 线程池,出于安全考虑,把他设为私有*/ private ExecutorService threadPool; private AppThreadManager(){ if (threadPool == null){ /** 确保只存在一个线程池,这是一个无界线程池*/ threadPool = Executors.newCachedThreadPool(); } } /** 获得线程管理器对象 <br> * 使用了double-check单例模式创建。 * @return */ public static AppThreadManager get(){ if (Instance == null){ synchronized (AppThreadManager.class){ if (Instance == null){ Instance = new AppThreadManager(); return Instance; } else return Instance; } } else return Instance; } /** * 启动一个任务 * @param runnable */ public void start(@NonNull Runnable runnable){ threadPool.execute(runnable); } /** * 使用submit()方法启动线程 * @param task * @param <T> * @return */ public <T> Future<T> submit(@NonNull Callable<T> task){ return threadPool.submit(task); } /** * 关闭线程池 */ public void stop(){ if (Instance == null){ return; } synchronized (this){ if(Instance != null){ threadPool.shutdownNow(); } Instance = null; } } }
相关文章推荐
- 《数据结构》10进制的数向任何进制的数进行转换
- uva572
- 关于信息安全专业学习的一些看法
- 一些软件设计的原则
- .Net工作流项目实战——前台到后台传值的编码、解码解决方案
- 【Unity Shader】自定义材质面板的小技巧
- U-Boot移植——添加新开发板
- Java_Filter
- 【Unity Shader】自定义材质面板的小技巧
- 机器学习-支持向量机SVM学习笔记一
- 213. House Robber II
- Windows上使用clang编译
- 关于数据精度
- mysql小记
- linux下EINTR的错误处理
- JBOSS实现RMI时注意的问题
- leetcode 121
- Java中会存在内存泄漏吗
- sql 小记
- 前端+移动开发