1.线程池理解
线程池在系统启动时即创建大量空闲的线程,程序将一个Runnable对象传给线程池,线程池就会启动一条线程来执行该对象的run方法,当run方法执行结束后,该线程并不会死亡,而是再次返回线程池中成为空闲状态,等待执行下一个Runnable对象的run方法。
线程池是为突然大量爆发的线程设计的,通过有限的几个固定线程为大量的操作服务,减少了创建和销毁线程所需的时间,从而提高效率。
线程池用于并发运行若干个执行时间不长且互不干预的任务。在JDK 1.5的java.lang.concurrent包里提供了实现线程池的方法。
2.线程池结构分析
1)线程池的生成
实现线程池的主要接口是ExecutorService,他实现了Executor接口, ExecutorService是通过ThreadPoolExecutor类实例化一个线程池的。而Executors是生成各种线程池的工厂。
//Executors工厂里生成CachedThreadPool线程池的一个方法
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
可以看出来,在Executors工厂里,通过ThreadPoolExecutor实例化了一个线程池。并返回ExecutorService 。
还有一种计划线程池,这种线程池主要用于定时任务和固定周期的重复任务,也就是ScheduledExecutorService,这个接口继承了ExecutorService ,这种线程池也是通过Executors工厂实例化的,在Executors工厂里,这种线程池是通过ScheduledThreadPoolExecutor来实例化的,ScheduledThreadPoolExecutor是继承了ThreadPoolExecutor类。
//Executors工厂里生产的计划任务
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
return new ScheduledThreadPoolExecutor(corePoolSize);
}
所以我们知道有两种线程池,分别是ExecutorService 和ScheduledExecutorService,而ScheduledExecutorService是继承了ExecutorService 。
(1)ExecutorService ,这个接口有四种线程池,分别是newCachedThreadPool,newFixedThreadPool,SingleThreadExecutor和newWorkStealingPool。
(2)ScheduledExecutorService有两种线程池,分别是newScheduledThreadPool和newSingleThreadScheduledExecutor。
2)执行任务
ExecutorService 执行任务有三个方法,分别是execute,submit和invoke。而ScheduledExecutorService,还有一个schedule方法。
1)execute
void execute(Runnable command);
接收 java.lang.Runnable 对象作为参数,并且以异步的方式执行它,执行这个方法是没有返回值的。
2)submit
Future<?> submit(Runnable task);
<T> Future<T> submit(Callable<T> task);
submit可以执行Runable和Callable的任务,会返回一个Future对象。
3)invoke
<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
throws InterruptedException;
<T> T invokeAny(Collection<? extends Callable<T>> tasks)
throws InterruptedException, ExecutionException;
invoke只执行Callable任务,有两个关于invoke的方法,分别是invokeAny和invokeAll。
4)schedule
public ScheduledFuture<?> schedule(Runnable command,
long delay, TimeUnit unit);
public <V> ScheduledFuture<V> schedule(Callable<V> callable,
long delay, TimeUnit unit);
这个方法是ScheduledExecutorService里的,也能执行Runable和Callable任务。
3)中断任务
线程池是可以中断的通过shutdown和shutdownNow。
(1)shutdown()
当线程池调用该方法时,线程池的状态则立刻变成SHUTDOWN状态。此时,则不能再往线程池中添加任何任务,否则将会抛出RejectedExecutionException异常。但是,此时线程池不会立刻退出,直到添加到线程池中的任务都已经处理完成,才会退出。
(2)shutdownNow()
根据JDK文档描述,大致意思是:执行该方法,线程池的状态立刻变成STOP状态,并试图停止所有正在执行的线程,抛出java.io.InterruptedIOException异常不再处理还在池队列中等待的任务,当然,它会返回那些未执行的任务。它试图终止线程的方法是通过调用Thread.interrupt()方法来实现的,但是大家知道,这种方法的作用有限,如果线程中没有sleep 、wait、Condition、定时锁等应用, interrupt()方法是无法中断当前的线程的。所以,ShutdownNow()并不代表线程池就一定立即就能退出,它可能必须要等待所有正在执行的任务都执行完成了才能退出。
3.例子解析
1)ExecutorService
(1)newCachedThreadPoo
/**
* @author Administrator 线程池的作用:
*
* 线程池是为突然大量爆发的线程设计的,通过有限的几个固定线程为大量的操作服务,减少了创建和销毁线程所需的时间,从而提高效率。
*
* 如果一个线程的时间非常长,就没必要用线程池了(不是不能作长时间操作,而是不宜。),况且我们还不能控制线程池中线程的开始、挂起、和中止。
*
* 线程池为无限大,newCachedThreadPool 只会重用空闲并且可用的线程,如果没有空闲的可用线程,就只能不停地创建新线程,这样可能会造成OOM
*/
public class TestnewCachedThreadPool extends Activity {
private ExecutorService executorService = null;
private String path = Environment.getExternalStorageDirectory()+"/lgyThreadPool/CachedThreadPool/";
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.test);
executorService = Executors.newCachedThreadPool();
executorService.submit(new DownTask("http://img.pconline.com.cn/images/upload/upc/tx/wallpaper/1206/18/c0/12043463_1339987116996.jpg", path, "img1.jpg"));
executorService.submit(new DownTask("http://img.pconline.com.cn/images/upload/upc/tx/wallpaper/1209/13/c0/13829920_1347512303112.jpg", path, "img2.jpg"));
executorService.submit(new DownTask("http://img5.imgtn.bdimg.com/it/u=376657532,1073811657&fm=23&gp=0.jpg", path, "img3.jpg"));
executorService.submit(new DownTask("http://www.shusp.com/wp-content/uploads/2015/11/4vAcI1TdZh3D07tWjctIFQvv5r1.jpg", path, "img4.jpg"));
}
}
(2)newFixedThreadPool
/**
* FixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待
*/
public class TestnewFixedThreadPool extends Activity {
private Button btn_cancel = null;
private ExecutorService executorService = null;
private String path = Environment.getExternalStorageDirectory()
+ "/lgyThreadPool/FixedThreadPool/";
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.test);
executorService = Executors.newFixedThreadPool(2);
executorService.submit(new DownTask("http://img.pconline.com.cn/images/upload/upc/tx/wallpaper/1206/18/c0/12043463_1339987116996.jpg", path, "img1.jpg"));
executorService.submit(new DownTask("http://img.pconline.com.cn/images/upload/upc/tx/wallpaper/1209/13/c0/13829920_1347512303112.jpg", path, "img2.jpg"));
executorService.submit(new DownTask("http://img5.imgtn.bdimg.com/it/u=376657532,1073811657&fm=23&gp=0.jpg", path, "img3.jpg"));
executorService.submit(new DownTask("http://www.shusp.com/wp-content/uploads/2015/11/4vAcI1TdZh3D07tWjctIFQvv5r1.jpg", path, "img4.jpg"));
btn_cancel = (Button) findViewById(R.id.button1);
btn_cancel.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (executorService!=null) {
//当线程池调用该方法时,线程池的状态则立刻变成SHUTDOWN状态。此时,则不能再往线程池中添加任何任务,
//否则将会抛出RejectedExecutionException异常。但是,此时线程池不会立刻退出,
//直到添加到线程池中的任务都已经处理完成,才会退出。
//executorService.shutdown();
//根据JDK文档描述,大致意思是:执行该方法,线程池的状态立刻变成STOP状态,并试图停止所有正在执行的线程,抛出java.io.InterruptedIOException异常
//不再处理还在池队列中等待的任务,当然,它会返回那些未执行的任务。
//它试图终止线程的方法是通过调用Thread.interrupt()方法来实现的,但是大家知道,这种方法的作用有限,
//如果线程中没有sleep 、wait、Condition、定时锁等应用, interrupt()方法是无法中断当前的线程的。
//所以,ShutdownNow()并不代表线程池就一定立即就能退出,它可能必须要等待所有正在执行的任务都执行完成了才能退出。
executorService.shutdownNow();
}
}
});
}
}
(3)newSingleThreadExecutor
/**
* SingleThreadExecutor创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。
*
*/
public class TestnewSingleThreadExecutor extends Activity {
private Button btn_cancel = null;
private ExecutorService executorService = null;
private String path = Environment.getExternalStorageDirectory()+"/lgyThreadPool/SingleThreadExecutor/";
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.test);
executorService = Executors.newSingleThreadExecutor();
executorService.submit(new DownTask("http://img.pconline.com.cn/images/upload/upc/tx/wallpaper/1206/18/c0/12043463_1339987116996.jpg", path, "img1.jpg"));
executorService.submit(new DownTask("http://img.pconline.com.cn/images/upload/upc/tx/wallpaper/1209/13/c0/13829920_1347512303112.jpg", path, "img2.jpg"));
executorService.submit(new DownTask("http://img5.imgtn.bdimg.com/it/u=376657532,1073811657&fm=23&gp=0.jpg", path, "img3.jpg"));
executorService.submit(new DownTask("http://www.shusp.com/wp-content/uploads/2015/11/4vAcI1TdZh3D07tWjctIFQvv5r1.jpg", path, "img4.jpg"));
//shutdown()可以让循环的任务终止
btn_cancel = (Button) findViewById(R.id.button1);
btn_cancel.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (executorService!=null) {
executorService.shutdown();
}
}
});
}
}
(4)newWorkStealingPool
/**
* WorkStealingPool,任务窃取线程池,可以实例化一个ForkJoinPool对象,这个线程池主要适合将大任务分成小任务来解决的。
* 创建一个线程池,保持足够的线程支持并行性水平,并可能使用多个队列减少争用。
*/
public class TestnewWorkStealingPool extends Activity {
private Button btn_cancel = null;
private ExecutorService executorService = null;
private ForkJoinPool forkJoinPool = null;
private String path = Environment.getExternalStorageDirectory()+"/lgyThreadPool/WorkStealingPool/";
@TargetApi(24) @Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.test);
executorService = Executors.newWorkStealingPool();
executorService.submit(new DownTask("http://img.pconline.com.cn/images/upload/upc/tx/wallpaper/1206/18/c0/12043463_1339987116996.jpg", path, "img1.jpg"));
executorService.submit(new DownTask("http://img.pconline.com.cn/images/upload/upc/tx/wallpaper/1209/13/c0/13829920_1347512303112.jpg", path, "img2.jpg"));
executorService.submit(new DownTask("http://img5.imgtn.bdimg.com/it/u=376657532,1073811657&fm=23&gp=0.jpg", path, "img3.jpg"));
executorService.submit(new DownTask("http://www.shusp.com/wp-content/uploads/2015/11/4vAcI1TdZh3D07tWjctIFQvv5r1.jpg", path, "img4.jpg"));
//shutdown()可以让循环的任务终止
btn_cancel = (Button) findViewById(R.id.button1);
btn_cancel.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (executorService!=null) {
executorService.shutdown();
}
}
});
}
}
2)ScheduledExecutorService
(1)newScheduledThreadPool
/**
* ScheduledThreadPool核心线程数量固定,当非核心线程闲置时立即回收,主要用于定时任务和固定周期的重复任务
*
*/
public class TestnewScheduledThreadPool extends Activity {
private Button btn_cancel = null;
private ScheduledExecutorService executorService = null;
private String path = Environment.getExternalStorageDirectory()+"/lgyThreadPool/ScheduledThreadPool/";
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.test);
executorService = Executors.newScheduledThreadPool(2);
//schedule(Runnable command, long delay, TimeUnit unit)
//schedule延时执行任务
//unit设置的是TimeUnit.SECONDS,即单位是秒,延时delay秒执行command任务
// executorService.schedule(new DownTask("http://img.pconline.com.cn/images/upload/upc/tx/wallpaper/1206/18/c0/12043463_1339987116996.jpg", path, "img1.jpg"), 1, TimeUnit.SECONDS);
// executorService.schedule(new DownTask("http://img.pconline.com.cn/images/upload/upc/tx/wallpaper/1209/13/c0/13829920_1347512303112.jpg", path, "img2.jpg"), 1, TimeUnit.SECONDS);
// executorService.schedule(new DownTask("http://img5.imgtn.bdimg.com/it/u=376657532,1073811657&fm=23&gp=0.jpg", path, "img3.jpg"), 1, TimeUnit.SECONDS);
// executorService.schedule(new DownTask("http://www.shusp.com/wp-content/uploads/2015/11/4vAcI1TdZh3D07tWjctIFQvv5r1.jpg", path, "img4.jpg"), 1, TimeUnit.SECONDS);
//scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit)
//scheduleAtFixedRate执行延时并有重复动作的任务
//unit设置的是TimeUnit.SECONDS,即单位是秒,第一次延时initialDelay秒执行,之后每period秒重复执行,如果上一次执行的时间超过了period秒,那么当上一次任务执行完成后将直接执行下一次任务,而不需再等待period秒再执行
// executorService.scheduleAtFixedRate(new DownTask("http://img.pconline.com.cn/images/upload/upc/tx/wallpaper/1206/18/c0/12043463_1339987116996.jpg", path, "img1.jpg"), 10, 1, TimeUnit.SECONDS);
//scheduleWithFixedDelay(command, initialDelay, delay, unit)
//scheduleWithFixedDelay执行延时并有重复动作的任务,但这个重复执行任务是阻塞的,只有执行完上一次任务,才会继续执行下一次任务
//unit设置的是TimeUnit.SECONDS,即单位是秒,第一次延时initialDelay秒执行,只有当上一次任务执行完成后才会执行下一次,(上一次执行完成后,延时delay秒执行)然后重复执行括号里的动作
// executorService.scheduleWithFixedDelay(new DownTask("http://img.pconline.com.cn/images/upload/upc/tx/wallpaper/1206/18/c0/12043463_1339987116996.jpg", path, "img1.jpg"), 1, 1, TimeUnit.SECONDS);
//shutdown()可以让循环的任务终止
btn_cancel = (Button) findViewById(R.id.button1);
btn_cancel.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (executorService!=null) {
executorService.shutdown();
}
}
});
}
}
(2)newSingleThreadScheduledExecutor
/**
* SingleThreadScheduledExecutor创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行,
* 他在SingleThreadExecutor的功能基础上,还能实现定时任务和固定周期的重复任务。
*
*/
public class TestnewSingleThreadScheduledExecutor extends Activity {
private Button btn_cancel = null;
private ScheduledExecutorService executorService = null;
private String path = Environment.getExternalStorageDirectory()+"/lgyThreadPool/SingleThreadScheduledExecutor/";
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.test);
executorService = Executors.newSingleThreadScheduledExecutor();
// executorService.submit(new DownTask("http://img.pconline.com.cn/images/upload/upc/tx/wallpaper/1206/18/c0/12043463_1339987116996.jpg", path, "img1.jpg"));
// executorService.submit(new DownTask("http://img.pconline.com.cn/images/upload/upc/tx/wallpaper/1209/13/c0/13829920_1347512303112.jpg", path, "img2.jpg"));
// executorService.submit(new DownTask("http://img5.imgtn.bdimg.com/it/u=376657532,1073811657&fm=23&gp=0.jpg", path, "img3.jpg"));
// executorService.submit(new DownTask("http://www.shusp.com/wp-content/uploads/2015/11/4vAcI1TdZh3D07tWjctIFQvv5r1.jpg", path, "img4.jpg"));
Log.i("lgy", "SingleThreadExecutor========");
executorService.schedule(new DownTask("http://img.pconline.com.cn/images/upload/upc/tx/wallpaper/1206/18/c0/12043463_1339987116996.jpg", path, "img1.jpg"), 10, TimeUnit.SECONDS);
executorService.schedule(new DownTask("http://img.pconline.com.cn/images/upload/upc/tx/wallpaper/1209/13/c0/13829920_1347512303112.jpg", path, "img2.jpg"), 10, TimeUnit.SECONDS);
executorService.schedule(new DownTask("http://img5.imgtn.bdimg.com/it/u=376657532,1073811657&fm=23&gp=0.jpg", path, "img3.jpg"), 2, TimeUnit.SECONDS);
executorService.schedule(new DownTask("http://www.shusp.com/wp-content/uploads/2015/11/4vAcI1TdZh3D07tWjctIFQvv5r1.jpg", path, "img4.jpg"), 2, TimeUnit.SECONDS);
//executorService.schedule运行结果:
// 03-30 15:34:56.050: I/lgy(25106): SingleThreadExecutor========
// 03-30 15:34:58.090: I/lgy(25106): img3.jpg is downloaded start
// 03-30 15:34:58.110: I/lgy(25106): img3.jpg is downloaded finish
// 03-30 15:34:58.200: I/lgy(25106): img4.jpg is downloaded start
// 03-30 15:34:58.470: I/lgy(25106): img4.jpg is downloaded finish
// 03-30 15:35:06.150: I/lgy(25106): img1.jpg is downloaded start
// 03-30 15:35:09.240: I/lgy(25106): img1.jpg is downloaded finish
// 03-30 15:35:09.490: I/lgy(25106): img2.jpg is downloaded start
// 03-30 15:35:13.510: I/lgy(25106): img2.jpg is downloaded finish
//shutdown()可以让循环的任务终止
btn_cancel = (Button) findViewById(R.id.button1);
btn_cancel.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (executorService!=null) {
executorService.shutdown();
}
}
});
}
}
4.参考文章
http://blog.csdn.net/lonelyroamer/article/details/7993637
http://blog.csdn.net/ns_code/article/details/17465497
http://justsee.iteye.com/blog/999189
网友评论