1.什么是线程池
线程池就是事先把多个线程放到一个容器中,当使用的时候不用new而是直接去线程池中拿即可,节省了开辟子线程的时间,提高代码执行效率。
2.线程池的优点
第一:降低资源消耗,通过重复利用已创建的线程降低线程创建和销毁造成的消耗
第二:提高响应速度,当任务到达时,任务可以不需要等到线程的创建就能执行
第三:提高线程的可管理性,线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控。
3.如何创建一个线程池
/**
* 项目中,线程池的管理类一般都是一个对象,所以这里用单例设计模式
*/
public class ThreadPoolManager {
private static ThreadPoolManager poolManager = new ThreadPoolManager();
//核心线程的数量,表示可以同时有多少个线程在运行
private int corePoolSize =Runtime.getRuntime().availableProcessors()*2+1;
//线程池的大小,表示该线程池一共可以容得下多少个线程,超过这个数目就会根据策略来执行,
// new ThreadPoolExecutor.AbortPolicy()一般用这个策略,表示抛弃
private int maximumPoolSize=corePoolSize;
//存活时间,表示在最大线程池中等待任务的线程的存活时间。
private long keepAliveTime=5;
//存活时间的单位
private TimeUnit unit=TimeUnit.SECONDS;
private ThreadPoolExecutor executor;
//通过单例设计模式来创建线程池的管理类
public static ThreadPoolManager getInstance(){
return poolManager;
}
private ThreadPoolManager(){
//创建线程池可以用ThreadPoolExecutor,也可以用Executors
executor = new ThreadPoolExecutor(
corePoolSize,
maximumPoolSize,
keepAliveTime,
unit,
//缓冲队列,超过核心线程的任务会被放到缓冲队列,
// 这个构造方法可以传入一个int值表示缓冲队列的数目,实际中我们一般不加,表示可以缓冲Integer.MAX_VALUE这么多个
//注意:任务和线程不一样,这里缓冲很多个不会造成内存溢出
new LinkedBlockingDeque<Runnable>(),
//这里一般这样写,使用默认的工厂
Executors.defaultThreadFactory(),
//当任务数超过线程池最大的数目时的策略,一般这样写
new ThreadPoolExecutor.AbortPolicy());
}
/**
* 添加任务的方法
* @param runnable
*/
public void execut(Runnable runnable){
if (runnable!=null){
executor.execute(runnable);
}
}
/**
* 移除任务的方法
* @param runnable
*/
public void remove (Runnable runnable){
if (runnable!=null){
executor.remove(runnable);
}
}
}
4.执行过程
(1)如果核心线程数还没到就放到核心线程去执行
(2)如果核心线程已满,则放到任务队列等待
(3)如果队列任务都满了,但还没有到达最大线程数,则开启一个非核心线程去执行任务
(4)如果到达了最大线程数,则抛异常
测试:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
System.out.println("模拟器的核心数:"+Runtime.getRuntime().availableProcessors());
for (int i = 0; i < 10; i++) {
ThreadPoolManager.getInstance().execut(new ThreadDemo(i));
}
}
class ThreadDemo implements Runnable{
public int num;
@Override
public void run() {
System.out.println(num+"-线程开始执行-----");
SystemClock.sleep(3000);//模拟线程执行事件
System.out.println(num+"-线程执行结束。。。");
}
public ThreadDemo(int num){
this.num = num;
System.out.println(num+"-线程等待执行");
}
}
}
结果输出:
System.out: 模拟器的核心数:2
System.out: 0-线程等待执行
System.out: 1-线程等待执行
System.out: 2-线程等待执行
System.out: 3-线程等待执行
System.out: 4-线程等待执行
System.out: 5-线程等待执行
System.out: 6-线程等待执行
System.out: 7-线程等待执行
System.out: 8-线程等待执行
System.out: 9-线程等待执行
System.out: 1-线程开始执行-----
System.out: 3-线程开始执行-----
System.out: 0-线程开始执行-----
System.out: 4-线程开始执行-----
System.out: 2-线程开始执行-----
System.out: 1-线程执行结束。。。
System.out: 5-线程开始执行-----
System.out: 3-线程执行结束。。。
System.out: 6-线程开始执行-----
System.out: 0-线程执行结束。。。
System.out: 7-线程开始执行-----
System.out: 4-线程执行结束。。。
System.out: 8-线程开始执行-----
System.out: 2-线程执行结束。。。
System.out: 9-线程开始执行-----
System.out: 5-线程执行结束。。。
System.out: 6-线程执行结束。。。
System.out: 7-线程执行结束。。。
System.out: 8-线程执行结束。。。
System.out: 9-线程执行结束。。。
网友评论