一、四种线程池
Java通过Executors提供四种线程池,分别为:
1、newSingleThreadExecutor 单一线程的线程池
创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。通过Executors中的newSingleThreadExecutor方法来创建,在这个线程池中只有一个核心线程,对于任务队列没有大小限制,也就意味着这一个任务处于活动状态时,其他任务都会在任务队列中排队等候依次执行。
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
newSingleThreadExecutor将所有的外界任务统一到一个线程中支持,所以在这个任务执行之间我们不需要处理线程同步的问题。
ExecutorService signalPool = Executors.newSingleThreadExecutor();
for (int i=0;i<10;i++){
final int i1 = i;
try{
Thread.sleep(1 * 1000);
}catch (Exception e){
e.printStackTrace();
}
signalPool.execute(new Runnable() {
@Override
public void run() {
Log.d("BOB",""+Thread.currentThread().getName() +"执行" +i1);
}
});
}
2、newFixedThreadPool 定长线程池
在这个线程池中 所容纳最大的线程数就是我们设置的核心线程数。 如果线程池的线程处于空闲状态的话,它们并不会被回收,除非是这个线程池被关闭。如果所有的线程都处于活动状态的话,新任务就会处于等待状态,直到有线程空闲出来。
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
由于newFixedThreadPool只有核心线程,并且这些线程都不会被回收,也就是 它能够更快速的响应外界请求 。从下面的newFixedThreadPool方法的实现可以看出,newFixedThreadPool只有核心线程,并且不存在超时机制,采用LinkedBlockingQueue,所以对于任务队列的大小也是没有限制的。
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);
for (int i=0;i<10;i++){
final int i1 = i;
try {
Thread.sleep(1*1000);
}catch (Exception e){
e.printStackTrace();
}
fixedThreadPool.execute(new Runnable() {
@Override
public void run() {
Log.d("BOB",""+Thread.currentThread().getName() +"执行" +i1);
}
});
}
3、newScheduledThreadPool
创建一个可定期或者延时执行任务的定长线程池,支持定时及周期性任务执行。
public ScheduledThreadPoolExecutor(int corePoolSize) {
super(corePoolSize, Integer.MAX_VALUE,
DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS,
new DelayedWorkQueue());
}
它的核心线程数是固定的,对于非核心线程几乎可以说是没有限制的,并且当非核心线程处于限制状态的时候就会立即被回收。
{
ScheduledExecutorService schedulePool = Executors.newScheduledThreadPool(3);
Runnable r1 = new Runnable() {
@Override
public void run() {
Log.d("BOB","延迟2秒执行 :"+" r1 "+Thread.currentThread().getName());
}
};
schedulePool.schedule(r1,2, TimeUnit.SECONDS);
Runnable r2 = new Runnable() {
@Override
public void run() {
Log.d("BOB","延迟3秒执行 :"+" r2 "+Thread.currentThread().getName());
}
};
schedulePool.schedule(r2,3,TimeUnit.SECONDS);
Runnable r3 = new Runnable() {
@Override
public void run() {
Log.d("BOB","延迟1秒执行 :"+" r3 "+Thread.currentThread().getName());
}
};
for (int i = 0; i<4; i++){
schedulePool.schedule(r3,1,TimeUnit.SECONDS);
}
}
4、newCachedThreadPoo 缓存线程池
创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。如果线程池的规模超过了处理需求,将自动回收空闲线程,而当需求增加时,则可以自动添加新线程,线程池的规模不存在任何限制
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
通过s上面的newCachedThreadPool方法在这里我们可以看出它的 核心线程数为0, 线程池的最大线程数Integer.MAX_VALUE。而Integer.MAX_VALUE是一个很大的数,也差不多可以说 这个线程池中的最大线程数可以任意大。
当线程池中的线程都处于活动状态的时候,线程池就会创建一个新的线程来处理任务。该线程池中的线程超时时长为60秒,所以当线程处于闲置状态超过60秒的时候便会被回收。 这也就意味着若是整个线程池的线程都处于闲置状态超过60秒以后,在newCachedThreadPool线程池中是不存在任何线程的,所以这时候它几乎不占用任何的系统资源。
对于newCachedThreadPool他的任务队列采用的是SynchronousQueue,上面说到在SynchronousQueue内部没有任何容量的阻塞队列。SynchronousQueue内部相当于一个空集合,我们无法将一个任务插入到SynchronousQueue中。所以说在线程池中如果现有线程无法接收任务,将会创建新的线程来执行任务。
案例代码
ExecutorService catchThreadPool = Executors.newCachedThreadPool();
for (int i=0 ;i<10;i++){
final int i1 = i;
try{
Thread.sleep(1 * 1000);
}catch (Exception e){
e.printStackTrace();
}
catchThreadPool.execute(new Runnable() {
@Override
public void run() {
Log.d("BOB",""+Thread.currentThread().getName() +"执行" +i1);
}
}
);
}