多线程之三:在线程池中的线程运行代码 (Running Code on a Thread Pool Thread)
2014-03-28 10:33
381 查看
上一篇向你展示了如何定一个类,管理线程池和运行在里面的任务。这一篇向你展示如何运行县城池里的一个任务。为了实现这个 ,你需要添加一个任务到线程池工作队列中。当一个线程变为可用状态时,ThreadPoolExecutor就从队列中取出一个任务并在线程上运行该任务。
这一篇也向你展示如何停止一个正在运行的任务。当任务开始之后,但是发现这个任务已经没有必要运行时,你可能需要停止这个正在运行的任务。与其浪费进程时间,不如你可以取消正在运行这任务的线程。例如,你正在从网络下载图片并且使用了缓存,如果你检测到需要的图片已经在缓存里面了你可能想停止这个任务。这些取决与你如何写你的app,在你开始现在之前你可能没有检测到这个图片。
在线程池中运行一个线程任务
为了在特殊的线程池中开始线程任务对象,并传递一个Runnable()到ThreadPoolExecutor.execute()中。这个调用加载了一个任务到线程池的工作队列。当一个休眠的线程变为可用时,管理器取出那个已经等待时间最长的任务,并在该线程上运行这个任务。
public class PhotoManager {
public void handleState(PhotoTask photoTask, int state) {
switch (state) {
// The task finished downloading the image
case DOWNLOAD_COMPLETE:
// Decodes the image
mDecodeThreadPool.execute(
photoTask.getPhotoDecodeRunnable());
...
}
...
}
...
}
当ThreadPoolExecutor开始一个Runnable在线程上, 它会自动调用run()方法。
中断正在运行的代码
为了停止一个任务,你需要中断这个任务的线程。为了准备这些,你需要在创建一个任务时存储该任务的一个handler。例如:
class PhotoDecodeRunnable implements Runnable {
// Defines the code to run for this task
public void run() {
/*
* Stores the current Thread in the
* object that contains PhotoDecodeRunnable
*/
mPhotoTask.setImageDecodeThread(Thread.currentThread());
...
}
...
}为了中断一个线程,调用Thread.interrupt()。注意线程对象是被系统控制,它可以在你的app进程外部修改线程对象。因为这个原因,你需要在中断一个线程之前锁定它入口,通过使用同步锁来占用该入口。例如:
public class PhotoManager {
public static void cancelAll() {
/*
* Creates an array of Runnables that's the same size as the
* thread pool work queue
*/
Runnable[] runnableArray = new Runnable[mDecodeWorkQueue.size()];
// Populates the array with the Runnables in the queue
mDecodeWorkQueue.toArray(runnableArray);
// Stores the array length in order to iterate over the array
int len = runnableArray.length;
/*
* Iterates over the array of Runnables and interrupts each one's Thread.
*/
synchronized (sInstance) {
// Iterates over the array of tasks
for (int runnableIndex = 0; runnableIndex < len; runnableIndex++) {
// Gets the current thread
Thread thread = runnableArray[taskArrayIndex].mThread;
// if the Thread exists, post an interrupt to it
if (null != thread) {
thread.interrupt();
}
}
}
}
...
}在多数情况下,Thread.interrupt()会立即停止线程。但是,它只会停止正在等待的线程,而不会中断CPU或者网络运行的任务。为了避免减低或者锁上系统资源,在尝试一个中断操作之前,你应该测试任何意图的中断请求:
/*
* Before continuing, checks to see that the Thread hasn't
* been interrupted
*/
if (Thread.interrupted()) {
return;
}
...
// Decodes a byte array into a Bitmap (CPU-intensive)
BitmapFactory.decodeByteArray(
imageBuffer, 0, imageBuffer.length, bitmapOptions);
...
这一篇也向你展示如何停止一个正在运行的任务。当任务开始之后,但是发现这个任务已经没有必要运行时,你可能需要停止这个正在运行的任务。与其浪费进程时间,不如你可以取消正在运行这任务的线程。例如,你正在从网络下载图片并且使用了缓存,如果你检测到需要的图片已经在缓存里面了你可能想停止这个任务。这些取决与你如何写你的app,在你开始现在之前你可能没有检测到这个图片。
在线程池中运行一个线程任务
为了在特殊的线程池中开始线程任务对象,并传递一个Runnable()到ThreadPoolExecutor.execute()中。这个调用加载了一个任务到线程池的工作队列。当一个休眠的线程变为可用时,管理器取出那个已经等待时间最长的任务,并在该线程上运行这个任务。
public class PhotoManager {
public void handleState(PhotoTask photoTask, int state) {
switch (state) {
// The task finished downloading the image
case DOWNLOAD_COMPLETE:
// Decodes the image
mDecodeThreadPool.execute(
photoTask.getPhotoDecodeRunnable());
...
}
...
}
...
}
当ThreadPoolExecutor开始一个Runnable在线程上, 它会自动调用run()方法。
中断正在运行的代码
为了停止一个任务,你需要中断这个任务的线程。为了准备这些,你需要在创建一个任务时存储该任务的一个handler。例如:
class PhotoDecodeRunnable implements Runnable {
// Defines the code to run for this task
public void run() {
/*
* Stores the current Thread in the
* object that contains PhotoDecodeRunnable
*/
mPhotoTask.setImageDecodeThread(Thread.currentThread());
...
}
...
}为了中断一个线程,调用Thread.interrupt()。注意线程对象是被系统控制,它可以在你的app进程外部修改线程对象。因为这个原因,你需要在中断一个线程之前锁定它入口,通过使用同步锁来占用该入口。例如:
public class PhotoManager {
public static void cancelAll() {
/*
* Creates an array of Runnables that's the same size as the
* thread pool work queue
*/
Runnable[] runnableArray = new Runnable[mDecodeWorkQueue.size()];
// Populates the array with the Runnables in the queue
mDecodeWorkQueue.toArray(runnableArray);
// Stores the array length in order to iterate over the array
int len = runnableArray.length;
/*
* Iterates over the array of Runnables and interrupts each one's Thread.
*/
synchronized (sInstance) {
// Iterates over the array of tasks
for (int runnableIndex = 0; runnableIndex < len; runnableIndex++) {
// Gets the current thread
Thread thread = runnableArray[taskArrayIndex].mThread;
// if the Thread exists, post an interrupt to it
if (null != thread) {
thread.interrupt();
}
}
}
}
...
}在多数情况下,Thread.interrupt()会立即停止线程。但是,它只会停止正在等待的线程,而不会中断CPU或者网络运行的任务。为了避免减低或者锁上系统资源,在尝试一个中断操作之前,你应该测试任何意图的中断请求:
/*
* Before continuing, checks to see that the Thread hasn't
* been interrupted
*/
if (Thread.interrupted()) {
return;
}
...
// Decodes a byte array into a Bitmap (CPU-intensive)
BitmapFactory.decodeByteArray(
imageBuffer, 0, imageBuffer.length, bitmapOptions);
...
相关文章推荐
- 求解,多线程时,线程池中一个线程内部代码抛出异常,那么这个线程能正常结束么?
- java线程一之创建线程、线程池以及多线程运行时间统计
- C++ windows多线程 线程描述了进程内代码的执行路径。进程中同时可以有多个线程在执行,为了使他们能够同时运行,操作系统为每个线程轮流分配CPU时间片,为了充分地利用CPU提高软件产品的性能,一
- 多线程--做单元测试时,使用线程池发现并没有运行指定代码,直接跳过
- 多线程发送操作之一:运行一个线程的格式化代码(Specifying the Code to Run on a Thread)
- 多线程并发库高级应用 之 java5中的线程并发库--线程池、Callable&Future
- C# 多线程学习(六)线程池(ThreadPool)——线程资源的复用和自动管理
- 线程代码多线程(二):更复杂一点的程序
- C# 多线程、异步线程、线程池相关知识
- java 线程、线程池基本应用演示样例代码回想
- 使用Interlocked在多线程下进行原子操作,无锁无阻塞的实现线程运行状态判断
- JAVA之旅(十二)——Thread,run和start的特点,线程运行状态,获取线程对象和名称,多线程实例演示,使用Runnable接口
- iOS多线程的初步研究(五)-- 如何让NSURLConnection在子线程中运行
- 本来要开始搬家~!~可CSDN又打不开,可能是我RP不好……贴一个这几天学会的老掉牙的技术——远线程运行汇编代码
- java 下计算质数的多线程跟单线程执行代码分析
- posix多线程有感--线程高级编程(线程属性函数总结)(代码)
- Android中的多线程处理(二)——使用线程池中的线程
- java多线程-线程运行状态-获取线程对象以及名称
- 线程池中的某个线程一直运行中, 某个 update sql 执行超时
- 多线程并发库高级应用 之 java5中的线程并发库--线程池、Callable&Future