______最近呢我那个不是很熟的长得有我几分姿色的朋友,维护大半年前写的代码的时候发现,代码的多处用到new Thread(new Runnable)创建线程,一点都不优雅,还好公司是自己一个人搞Android,不然迟早被打死,为了让他不被揍,写个文章然他长长记性。
一、基本线程池
______该线程池存在核心线程和非核心线程,顾名思义核心线程就是一创建就会一直存在,一直运行run任务或者等待任务,非核心线程就是==不是核心的线程==,只会在任务队列满了后创建,而且在空闲一段时间后会被回收释放资源。
简单使用
//基本线程池使用
private final ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
2, //核心线程数
5,//总线程数 非核心=总数-核心
3,//非核心线程空闲时等闲下一个任务的时间 当任务量很大的时候 调大这个参数可以提高线程的利用率
TimeUnit.SECONDS,//上面那个参数的单位
new LinkedBlockingDeque<>(4)//任务队列
);
public void ordinaryTreadPool(View view) {
for (int i = 0; i < 7; i++) {
Runnable runnable = new Runnable() {
@Override
public void run() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.d(TAG, "ThreadPool: 线程打印 "+Thread.currentThread().getName());
}
};
threadPoolExecutor.execute(runnable);
}
}
可以看到上面的非核心线程有5-2=3个,任务队列有4个,进入线程池的任务有7个,因为7-2>4任务队列满了,所以运行结果会多叫一个非核心线程pool-1-thread-3去帮忙1,2是核心线程。
ThreadPool: 线程打印 pool-1-thread-1
ThreadPool: 线程打印 pool-1-thread-2
ThreadPool: 线程打印 pool-1-thread-3
ThreadPool: 线程打印 pool-1-thread-2
ThreadPool: 线程打印 pool-1-thread-1
ThreadPool: 线程打印 pool-1-thread-3
ThreadPool: 线程打印 pool-1-thread-2
二、可重用固定线程数线程池(Executors.newFixedThreadPool)
______这个也顾名思义,就是只有估计的线程数,没有核心非核心之分
简单使用
//固定线程数
private final ExecutorService executorService = Executors.newFixedThreadPool(5);//线程数为5
public void fixedNumTreadPool(View view) {
for (int i = 0; i < 7; i++) {
Runnable runnable = new Runnable() {
@Override
public void run() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.d(TAG, "FixedThreadPool: 线程打印 " + Thread.currentThread().getName());
}
};
executorService.execute(runnable);
}
}
结果:
线程打印 pool-2-thread-2
线程打印 pool-2-thread-5
线程打印 pool-2-thread-3
线程打印 pool-2-thread-4
线程打印 pool-2-thread-1
线程打印 pool-2-thread-3
线程打印 pool-2-thread-5
三、按虚创建线程池
______顾名思义,有需要多少就创建多少线程,但是空闲等待时间是60s,过后就被回收了
简单使用
//按需创建
private final ExecutorService executorCachedService = Executors.newCachedThreadPool();
public void cachedTreadPool(View view) {
for (int i = 0; i < 7; i++) {
Runnable runnable = new Runnable() {
@Override
public void run() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.d(TAG, "CachedThreadPool: 线程打印 " + Thread.currentThread().getName());
}
};
executorCachedService.execute(runnable);
}
}
CachedThreadPool: 线程打印 pool-3-thread-3
CachedThreadPool: 线程打印 pool-3-thread-2
CachedThreadPool: 线程打印 pool-3-thread-4
CachedThreadPool: 线程打印 pool-3-thread-1
CachedThreadPool: 线程打印 pool-3-thread-6
CachedThreadPool: 线程打印 pool-3-thread-7
CachedThreadPool: 线程打印 pool-3-thread-5
可以看出直接打印打印七个任务七个线程了,这是因为线程处理一次要2秒,这两秒内没有空闲的就都创建了,试试吧那等待两秒去了为了更明显 我们把加入的线程从7个改成10个,然后就会发现
CachedThreadPool: 线程打印 pool-3-thread-1
CachedThreadPool: 线程打印 pool-3-thread-2
CachedThreadPool: 线程打印 pool-3-thread-3
CachedThreadPool: 线程打印 pool-3-thread-4
CachedThreadPool: 线程打印 pool-3-thread-2
CachedThreadPool: 线程打印 pool-3-thread-3
CachedThreadPool: 线程打印 pool-3-thread-1
CachedThreadPool: 线程打印 pool-3-thread-4
CachedThreadPool: 线程打印 pool-3-thread-5
CachedThreadPool: 线程打印 pool-3-thread-6
只创建了6个线程,复用了,所以这个适用于有大量需要立即执行的耗时少的任务的情况。
四、单个核心线程线程池
______还是顾名思义,只有一个核心线程的线程池
简单使用
//单个核心线程
private final ExecutorService executorSingleService = Executors.newSingleThreadExecutor();
public void singleTreadPool(View view) {
for (int i = 0; i <10; i++) {
Runnable runnable = new Runnable() {
@Override
public void run() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.d(TAG, "CachedThreadPool: 线程打印 " + Thread.currentThread().getName());
}
};
executorSingleService.execute(runnable);
}
}
CachedThreadPool: 线程打印 pool-4-thread-1
CachedThreadPool: 线程打印 pool-4-thread-1
CachedThreadPool: 线程打印 pool-4-thread-1
CachedThreadPool: 线程打印 pool-4-thread-1
CachedThreadPool: 线程打印 pool-4-thread-1
CachedThreadPool: 线程打印 pool-4-thread-1
CachedThreadPool: 线程打印 pool-4-thread-1
CachedThreadPool: 线程打印 pool-4-thread-1
CachedThreadPool: 线程打印 pool-4-thread-1
CachedThreadPool: 线程打印 pool-4-thread-1
可以发现 每两秒执行一次
五、可延迟定时线程池
______不多说,顾名思义
简单用法
//可定时延迟线程池
private final ScheduledExecutorService executorDelayService = Executors.newScheduledThreadPool(3);//核心线程数
public void delayTreadPool(View view) {
Runnable runnable = new Runnable() {
@Override
public void run() {
Log.d(TAG, "executorDelayService: 线程打印 " + Thread.currentThread().getName());
}
};
// executorDelayService.schedule(runnable,5,TimeUnit.SECONDS);//延迟五秒开始
executorDelayService.scheduleAtFixedRate(runnable, 3, 2, TimeUnit.SECONDS);//延迟3秒开始后每两秒执行一次
// executorDelayService.scheduleWithFixedDelay(runnable, 3, 2, TimeUnit.SECONDS);//开始后第一次延迟3秒 后面都每两秒执行一次
}
最后
别忘了关闭线程池
poll.shutDown() 关闭线程池,不影响运行中的任务
poll.shutDownNow() 关闭线程池,并尝试去终止正在执行的线程