Skip to content

Latest commit

 

History

History
190 lines (159 loc) · 6.42 KB

将操作发送到多个线程——(4)在线程池中的线程中运行代码.md

File metadata and controls

190 lines (159 loc) · 6.42 KB

将操作发送到多个线程——在线程池中的线程中运行代码

原文(英文)地址

上一篇文章 为多线程创建管理者(manager),介绍了如何定义管理线程池的类。本文主要介绍如何在线程池上运行任务。为了在线程池上运行任务,您应该将任务添加到线程池的工作队列中。当有线程可用时,ThreadPoolExecutor会从队列中获取一个任务并在线程上运行它。

本文还向您展示了如何停止正在运行的任务。如果任务启动,但随后发现其工作不是必需的,您可以取消运行任务的线程,而不是浪费处理器时间。例如,如果从网络下载图像并使用缓存,则可能需要在检测到缓存中已存在图像时停止任务。

在线程池中的线程上运行任务

要在特定线程池中的线程上启动任务,请将Runnable传递给ThreadPoolExecutor.execute()。此调用将任务添加到线程池的工作队列中,当有空闲线程可用时,管理器将获取等待时间最长的任务并在线程上运行它:

  • kotlin

  • object PhotoManager {
    
        fun handleState(photoTask: PhotoTask, state: Int) {
            when (state) {
                DOWNLOAD_COMPLETE ->
                    // Decodes the image
                    decodeThreadPool.execute(photoTask.getPhotoDecodeRunnable())
                ...
            }
            ...
        }
        ...
    }
  • java

  • public class PhotoManager {
        public void handleState(PhotoTask photoTask, int state) {
            switch (state) {
                // The task finished downloading the image
                case DOWNLOAD_COMPLETE:
                // Decodes the image
                    decodeThreadPool.execute(
                            photoTask.getPhotoDecodeRunnable());
                ...
            }
            ...
        }
        ...
    }

当ThreadPollExecutor在一个线程中启动Runnable类之后,它会自动调用Runnable类的run()方法。

中断正在执行的代码

要停止一个任务,你需要中断执行该任务的线程。要实现此操作,您需要在创建任务时将句柄存储到任务的线程。例如:

  • kotlin
 class PhotoDecodeRunnable : Runnable {
 
     // Defines the code to run for this task
     override fun run() {
         /*
          * Stores the current Thread in the
          * object that contains PhotoDecodeRunnable
          */
         photoTask.setImageDecodeThread(Thread.currentThread())
         ...
     }
     ...
 }
  • java
 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
          */
         photoTask.setImageDecodeThread(Thread.currentThread());
         ...
     }
     ...
 }

要中断线程,请调用Thread.interrupt()。请注意,Thread对象由系统控制,系统可以在应用程序的进程外修改它们。因此,您需要在中断之前获取该线程的锁以获取该线程的访问权限,方法是将访问置于synchronized块中。例如:

  • kotlin
 object PhotoManager {
     fun cancelAll() {
         /*
          * Creates and populates an array of Runnables with the Runnables in the queue
          */
         val runnableArray: Array<Runnable> = decodeWorkQueue.toTypedArray()
         /*
          * Iterates over the array of Runnables and interrupts each one's Thread.
          */
         synchronized(this) {
             // Iterates over the array of tasks
             runnableArray.map { (it as? PhotoDecodeRunnable)?.mThread }
                     .forEach { thread ->
                         thread?.interrupt()
                     }
         }
     }
     ...
 }
  • java
 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[decodeWorkQueue.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
                 Runnable runnable = runnableArray[runnableIndex];
                 Thread thread = null;
                 if (runnable instanceof PhotoDecodeRunnable) {
                     thread = ((PhotoDecodeRunnable)runnable).mThread;
                 }
                 // if the Thread exists, post an interrupt to it
                 if (null != thread) {
                     thread.interrupt();
                 }
             }
         }
     }
     ...
 }

在大多数情况下,Thread.interrupt()会立即停止线程。但是,它只会停止正在等待的线程,并且不会中断CPU或网络密集型任务。为避免减慢或锁定系统,您应该在尝试操作之前测试任何挂起的中断请求:

  • kotlin
 /*
  * 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.size, bitmapOptions)
 ...
  • java
 /*
  * 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);
 ...

更多内容

更多内容请参阅进程和线程——概述