1. 为什么要引入线程池?
如果有100个下载任务,每次 new Thread(),很耗性能;
new多个线程也缺乏管理,线程过多之间会相互竞争,占用资源多,导致系统瘫痪;
所以就引入线程池;
2. 线程池好处?
解决了线程反复的创建和销毁,做到线程可以反复使用;
3. ExecutorService介绍?
ExecutorService是线程池,是一个接口,继承自Executor接口;
4. Executors工厂类
Executors工厂类提供四种线程池:newSingleThreadExecutor、newScheduledThreadPool、newCacheThreadPool、newFixedThreadPool;
1>:newSingleThreadExecutor用法
创建一个单线程的线程池,它只用这一个线程来完成20个任务,保证所有任务按照指定顺序执行;
代码如下:
/**
* 单线程的线程池:
* 只会用一个线程来执行任务,保证所有任务按照指定顺序执行
*/
private void newSingleThreadExecutor() {
ExecutorService singleThreadPool = Executors.newSingleThreadExecutor();
for (int i = 1; i <= number; i++) {
final int index = i;
singleThreadPool.execute(new Runnable() {
@SuppressLint("LongLogTag")
@Override
public void run() {
String threadName = Thread.currentThread().getName();
Log.e("TAG", "线程:"+threadName+",正在执行第" + index + "个任务");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
}
运行结果如下:
图片.png
可以看到:
总共只创建一个线程,第一个执行完之后再去执行第二个,第二个执行完再去执行第三个...;
2>:newScheduledThreadPool用法
创建一个定长线程,可以执行定时的、周期性的任务;
代码如下:
/**
* 每次创建一个定长的线程:
* 可执行定时的、周期性的任务
*/
private void newScheduledThreadPool() {
ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);
//延迟2秒后执行该任务
scheduledThreadPool.schedule(new Runnable() {
@SuppressLint("LongLogTag")
@Override
public void run() {
String threadName = Thread.currentThread().getName();
Log.e("TAG", "线程:" + threadName + ",正在执行");
}
}, 2, TimeUnit.SECONDS);
//延迟1秒后,每隔2秒执行一次该任务
scheduledThreadPool.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
String threadName = Thread.currentThread().getName();
Log.e("TAG", "线程:" + threadName + ",正在执行");
}
}, 1, 2, TimeUnit.SECONDS);
}
运行结果如下:
图片.png
可以看到:
每次只是创建一个线程,每隔2秒执行一次;
3>:newCacheThreadPool:
创建一个可缓存的线程池,如果线程池长度超过处理需要,可以回收空闲的线程;
代码如下:
/**
* 可缓存的线程池:
* 如果线程池超过处理需要,可回收空闲线程
*/
private void newCachedThreadPool() {
ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
for (int i = 1; i <= number; i++) {
final int index = i;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
cachedThreadPool.execute(new Runnable() {
@Override
public void run() {
String threadName = Thread.currentThread().getName();
Log.e("TAG", "线程:" + threadName + ",正在执行第" + index + "个任务");
try {
long time = index * 500;
Thread.sleep(time);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
}
运行结果如下:
图片.png
可以看到:
a:缓存线程池大小不固定,可以创建多个线程;
b:在使用缓存线程池时候,先查看线程池中是否有以前创建的线程,如果有,就复用;如果没有,就创建线程,然后添加到线程池中;
c:缓存的线程池通常用于执行生存期比较短的异步任务;
4>:newFixedThreadPool用法
创建一个可重用的、固定的线程数的线程池;
代码如下:
/**
* 可重用的、固定的线程数的线程池
* 固定的线程数是5
*/
private void newFixedThreadPool() {
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(5);
for (int i = 1; i <= number; i++) {
final int index = i;
fixedThreadPool.execute(new Runnable() {
@Override
public void run() {
String threadName = Thread.currentThread().getName();
Log.e("TAG", "线程:"+threadName+",正在执行第" + index + "个任务");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
}
运行结果如下:
图片.png
可以看到:
a:只会创建5个线程来执行任务,其余的任务都添加在 缓存队列中,当线程池中的线程执行完之后,再从 缓存队列中取任务继续执行;