コンテンツに移動

よくアクセスするページ

最近アクセスしたページ

navigation

Running Code on a Thread Pool Thread

This lesson teaches you to

  1. Run a Runnable on a Thread in the Thread Pool
  2. Interrupt Running Code

You should also read

Try it out

Download the sample

ThreadSample.zip

The previous lesson showed you how to define a class that manages thread pools and the tasks that run on them. This lesson shows you how to run a task on a thread pool. To do this, you add the task to the pool's work queue. When a thread becomes available, the ThreadPoolExecutor takes a task from the queue and runs it on the thread.

This lesson also shows you how to stop a task that's running. You might want to do this if a task starts, but then discovers that its work isn't necessary. Rather than wasting processor time, you can cancel the thread the task is running on. For example, if you are downloading images from the network and using a cache, you probably want to stop a task if it detects that an image is already present in the cache. Depending on how you write your app, you may not be able to detect this before you start the download.

Run a Task on a Thread in the Thread Pool

To start a task object on a thread in a particular thread pool, pass the Runnable to ThreadPoolExecutor.execute(). This call adds the task to the thread pool's work queue. When an idle thread becomes available, the manager takes the task that has been waiting the longest and runs it on the thread:

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());
            ...
        }
        ...
    }
    ...
}

When ThreadPoolExecutor starts a Runnable on a thread, it automatically calls the object's run() method.

Interrupt Running Code

To stop a task, you need to interrupt the task's thread. To prepare to do this, you need to store a handle to the task's thread when you create the task. For example:

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());
        ...
    }
    ...
}

To interrupt a thread, call Thread.interrupt(). Notice that Thread objects are controlled by the system, which can modify them outside of your app's process. For this reason, you need to lock access on a thread before you interrupt it, by placing the access in a synchronized block. For example:

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();
                }
            }
        }
    }
    ...
}

In most cases, Thread.interrupt() stops the thread immediately. However, it only stops threads that are waiting, and will not interrupt CPU or network-intensive tasks. To avoid slowing down or locking up the system, you should test for any pending interrupt requests before attempting an operation :

/*
 * 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);
...
このサイトでは、ユーザーが選択したサイトの言語と表示設定を保存する目的で Cookie を使用しています。

Android デベロッパー向けの最新情報やヒントを入手して、Google Play での成功を手に入れましょう。

* 必須

送信しました

WeChat で Google Developers をフォローする

このサイトをで表示しますか?

ページの表示言語としてを選択しましたが、このサイトの言語はに設定されています。

言語設定を変更してこのサイトをで表示しますか?言語設定を変更する場合は、各ページの下にある言語メニューを使用してください。

このクラスには、API レベル 以上が必要です。

API レベル が選択されているため、このドキュメントは非表示になっています。左のナビゲーションの上にあるセレクタを使って、ドキュメントの API レベルを変更できます。

アプリに必要な API レベルを指定する方法について、詳しくは異なるプラットフォーム バージョンのサポートをご覧ください。

Take a short survey?
Help us improve the Android developer experience. (April 2018 — Developer Survey)