线程池
线程池是一种对象池的概念,目的是减小对象的创建和注销的开支,减轻JVM的压力。
为什么使用线程池?
newThread有很多弊端
1、新建对象性能差
2、线程之间缺乏统一的管理,可能无限创建线程,相互之间竞争会带来过多的系统损耗,导致死机或者oom
3、缺乏更多的功能,例如定时执行,定期执行,线程中断,可以基本理解为线程池扩展了很多新功能
TimeUnit类中有7种静态属性:
TimeUnit.DAYS; //天
TimeUnit.HOURS; //小时
TimeUnit.MINUTES; //分钟
TimeUnit.SECONDS; //秒
TimeUnit.MILLISECONDS; //毫秒
TimeUnit.MICROSECONDS; //微妙
TimeUnit.NANOSECONDS; //纳秒
Executors提供四种线程池,分别为:
- newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
ExecutorService CachedPool= Executors.newCachedThreadPool();
for (int i=0;i<1000;i++){
final int index=i;
try {
Thread.sleep(index*1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
CachedPool.execute(new Runnable() {
@Override
public void run() {
Log.i("数据打印",""+index);
}
});
}
线程池为无限大,当执行第二个任务时第一个任务已经完成,会复用执行第一个任务的线程,而不用每次新建线程。
- newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
ExecutorService fixedThreadPool=Executors.newFixedThreadPool(1000);
for (int i=0;i<1000;i++){
final int index=i;
fixedThreadPool.execute(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(index*1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.i("数据打印",""+index);
}
});
}
- newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, 优先级)执行。
ExecutorService singlePool=Executors.newSingleThreadExecutor();
for (int i=0;i<10;i++){
final int index=i;
singlePool.execute(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(index*1000);
Log.i("数据打出来",""+index);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
结果依次输出,相当于顺序执行各个任务。
- newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。
ScheduledExecutorService schemedPool=Executors.newScheduledThreadPool(5);
//延时操作.操作任务,延迟的时间,延迟事件
schemedPool.schedule(new Runnable() {
@Override
public void run() {
Log.i("数据打印","任务执行完毕");
}
},3, TimeUnit.SECONDS);
表示延迟3秒执行。
定时周期性任务
//定时周期性任务
schemedPool.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
Log.i("","");
}
},0,5,TimeUnit.SECONDS);
表示延迟0秒后每5秒执行一次。
ScheduledExecutorService比Timer更安全,功能更强大,与前面的单独进行对比。