本节展示如何在线程池里执行任务。流程是,添加一个任务到线程池的工作队列,当有线程可用时(执行完其他任务,空闲,或者还没执行任务),ThreadPoolExecutor会从队列里取任务,并在线程里运行。 本课同时向你展示了如何停止正在运行的任务。 在线程池里的线程上执行任务 在ThreadPoolExecutor.execute()里传入 Runnable对象启动任务。这个方法会把任务添加到线程池工作队列。当有空闲线程时,管理器会取出等待最久的任务,在线程上运行。 复制代码 代码如下: 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()方法。 中断正在运行的代码 要停止任务,你需要中断任务的进程。你需要在创建任务的时候,保存一个当前线程的handle. 如: 复制代码 代码如下: 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或network-intensive任务。为了避免系统变慢,你应该在开始尝试操作前测试等待中断的请求。 复制代码 代码如下: /* * 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); ...