Java实战篇-线程池管理
Java简单实战⼼得
线程池(Thread Pool)
定义
⼀种线程的使⽤模式,它可以管理整个项⽬线程任务,因为线程的创建和销毁会消耗⼤量的cpu资源,且线程不能⽆节制的开启占⽤系统运存,所以需要⽤⼀个对象来管理线程数量的使⽤,像池⼦⼀样有⼀定⼤⼩的容量限制和尽可能地减少线程的创建和销毁。
特点
1.⼀般⼀个项⽬就⼀个线程池,单例模式;
2.限制线程数量;
3.减少线程的创建和销毁。
如何定制池⼦⼤⼩
根据服务系统是CPU密集型还是I/O密集型,适当选择线程数量的多少,CPU运⾏速度⼀般都是⽐I/O数据流读写的速度快得多,所以CPU 密集型的线程数量较少,⼀般池⼦限制的线程数为(CPU数量 + 1)个,⽽为了提⾼I/O的操作效率,减少CPU等待时间,I/O密集型限制的线程数为(2 ✖ CPU数量)个。
参数
安卓原⽣类ThreadPoolExecutor的输⼊参数如下:
参数名作⽤
int corePoolSize核⼼线程数的数量,这些线程即使处于空闲状态也不会被销毁
int maximumPoolSize线程池最⼤线程数量
long keepAliveTime空闲线程存活时间,即线程池⾥除了核⼼线程的其他线程
TimeUnit unit空闲线程存活时间单位,有
BlockingQueue
workQueue
阻塞队列,⽤于保存待执⾏的线程,常⽤的有
ThreadFactory
threadFactory
线程⼯⼚,ThreadFactory是⼀个接⼝,该接⼝只包含如下⽅法:Thread newThread(Runnable r);
RejectedExecutionHandler
handler 拒绝策略,RejectedExecutionHandler也是⼀个接⼝,该接⼝只包含如下⽅法:void rejectedExecution(Runnable r,
ThreadPoolExecutor executor); 安卓原⽣提供了实现
时间单位TimeUnit可选参数时间间隔⼤⼩TimeUnit.DAYS天
TimeUnit.HOURS⼩时
TimeUnit.MINUTES分钟
TimeUnit.SECONDS秒TimeUnit.MILLISECONDS毫秒
TimeUnit.MICROSECONDS微秒
TimeUnit.NANOSECONDS纳秒
阻塞队列
BlockingQueue可选参
数
作⽤
LinkedBlockingQueue 链表结构的阻塞队列,有任务时,⼀是当前线程数⼩于核⼼线程数,则新建核⼼线程数执⾏任务,⼆是当前线程数⼤于等于核⼼线程数,则任务进⼊该队列等待,该队列导致最⼤线程数的设置失效,因为总可线程数被限制在了核⼼线程数
SynchronousQueue 同步队列,该队列接收到任务则直接处理,核⼼线程满了则继续新建⾮核⼼线程⼯作,所以⼀般设置最⼤线程数为⼀个很⼤的数
Integer.MAX_VALUE,当达到最⼤线程数则执⾏拒绝策略
ArrayBlockingQueue 数组结构的阻塞队列,使⽤该队列时,需指定数组⼤⼩。有任务时,⼀是当前线程数⼩于核⼼线程数,则新建核⼼线程数执⾏任务,⼆是当前线程数⼤于等于核⼼线程数,则任务进⼊该队列等待,三是当队列⾥的任务已满初始化时的数组⼤⼩,则新建⾮核⼼线程执⾏任务,直到线程数达到最⼤线程数时,则执⾏拒绝策略
拒绝策略RejectedExecutionHandler可选参数作⽤
AbortPolicy抛出异常
CallerRunsPolicy线程池不shutdown的情况下,执⾏被拒绝任务的run⽅法
DiscardPolicy什么都不做
DiscardOldestPolicy抛弃最早进⼊队列的任务,尝试把被拒绝的任务加⼊队列⼀般写法
import urrent.ArrayBlockingQueue;
import urrent.BlockingQueue;
import urrent.RejectedExecutionHandler;
import urrent.ThreadFactory;
import urrent.ThreadPoolExecutor;
import urrent.TimeUnit;
import urrent.atomic.AtomicInteger;
/**
* 线程池管理器
*/
public class ThreadPoolManager {
// ⽤单例模式对线程进⾏管理
private static volatile ThreadPoolExecutor singleTon = null;
/
/ 获取可⽤CPU数量
private static final int CPU_NUM = Runtime().availableProcessors();
// 以 CPU 密集型为例
private static final int CORE_POOL_SIZE = CPU_NUM +1;
// 设置最⼤线程数等于核⼼线程数
private static final int MAXIMUM_POOL_SIZE = CORE_POOL_SIZE;
// ⾮核⼼线程存活时间100毫秒
private static final long KEEP_ALIVE_TIME =100;
// 时间单位设置为毫秒
private static final TimeUnit UNIT = TimeUnit.MILLISECONDS;
java线程池创建的四种// 初始化数组结构阻塞队列的⼤⼩为 5
private static final BlockingQueue<Runnable> WORK_QUEUE =new ArrayBlockingQueue<>(5);
// ⾃定义个线程创建⼯⼚
private static final ThreadFactory THREAD_FACTORY =new MyThreadFactory();
// 使⽤安卓原⽣异常抛出策略
private static final RejectedExecutionHandler HANDLER =new ThreadPoolExecutor.AbortPolicy();
public static ThreadPoolExecutor getInstance(){
if(singleTon == null){
synchronized(ThreadPoolManager.class){
if(singleTon == null){
singleTon =new ThreadPoolExecutor(CORE_POOL_SIZE,
MAXIMUM_POOL_SIZE, KEEP_ALIVE_TIME, UNIT,
WORK_QUEUE, THREAD_FACTORY, HANDLER);
}
}
}
return singleTon;
}
/**
* ⾃定义线程⽣成⼯⼚,该类为
* 每个线程增加⼀个计数标识
*/
private static class MyThreadFactory implements ThreadFactory {
/
/ 从1开始增长打印线程名
AtomicInteger atomicInteger =new AtomicInteger(1);
@Override
public Thread newThread(Runnable r){
Thread thread =new Thread(r, String.AndIncrement()));
return thread;
}
}
}
测试⽅法
public static void main(String[] args){
Runnable runnable =new Runnable(){
@Override
public void run(){
// 打印当前线程名字
System.out.println(Thread.currentThread().getName());
}
};
for(int i =0; i <10; i++){
// 往线程池提交10次
}
/
/ 关闭线程池
}
测试结果
2
4
7
3
1
5
6
5
8
9
JDK⾃带的线程池管理类
原⽣JDK⾃带四种基于ThreadPoolExecutor实现的线程池管理类,如果懒得⾃⼰去实现就直接⽤吧,如下,假如我们有⼀个Runnable对象runnable:
// 线程池核⼼线程数为 0 和最⼤线程数为 Integer.MAX_VALUE
ExecutorService cachedThreadPool = wCachedThreadPool();
cachedThreadPool.submit(runnable);
// 线程池核⼼线程数和最⼤线程数为⾃定义数字,下⾯的例⼦为 3
ExecutorService fixedThreadPool = wFixedThreadPool(3);
fixedThreadPool.submit(runnable);
// 线程池核⼼线程为⾃定义数字,下⾯的例⼦为5个,该线程池为周期性或定期执⾏任务,下⾯例⼦延迟1秒,每3秒执⾏⼀次ScheduledExecutorService scheduledThreadPool = wScheduledThreadPool(5);
scheduledThreadPool.scheduleAtFixedRate(runnable,1,2, TimeUnit.SECONDS);
// 线程池的核⼼线程和最⼤线程数均为 1
ExecutorService singleThreadExecutor = wSingleThreadExecutor();
singleThreadExecutor.submit(runnable);
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论