0

所以我创建了一个单例线程池:

线程池.java

package utils;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import android.annotation.SuppressLint;
import android.os.Handler;
import android.os.Message;
import android.util.Log;

public class TaskManager {

    // Sets the amount of time an idle thread will wait for a task before
// terminating
private static final int KEEP_ALIVE_TIME = 30;

// Sets the Time Unit to seconds
private static final TimeUnit KEEP_ALIVE_TIME_UNIT;

private static final int CORE_POOL_SIZE = 2;

private static final int MAXIMUM_POOL_SIZE = 2;

// A queue of Runnable for the image download pool
private final BlockingQueue<Runnable> mTaskQueue;

// A managed pool of background download threads
private final ThreadPoolExecutor mTaskThreadPool;

private static TaskManager sInstance = null;

private Handler mHandler;

// A static block that sets class fields

static {
    // The time unit for "keep alive" is in seconds
    KEEP_ALIVE_TIME_UNIT = TimeUnit.SECONDS;

    // Creates a single static instance of PhotoManager
    if (sInstance == null) {
        sInstance = new TaskManager();
        Log.d("init", "new TaskManager");
    }

}

public Handler getHandler() {
    return mHandler;
}

@SuppressLint("HandlerLeak")
private TaskManager() {
    mTaskQueue = new LinkedBlockingQueue<Runnable>();

    mTaskThreadPool = new ThreadPoolExecutor(CORE_POOL_SIZE,
            MAXIMUM_POOL_SIZE, KEEP_ALIVE_TIME, KEEP_ALIVE_TIME_UNIT,
            mTaskQueue);

    mHandler = new Handler() {
        public void handleMessage(Message m) {
            switch (m.what) {
            case 0:
                Log.d("start", (String) m.obj);
                break;
            case 1:
                Log.d("finish", (String) m.obj);
                break;
            }
        }
    };
}

public static TaskManager getInstance() {
    return sInstance;
}

public void addTask(Runnable task) {
    sInstance.mTaskQueue.offer(task);
    Log.d("size after add", Integer.toString(sInstance.mTaskQueue.size()));
}

public void startTask() {
    if (!sInstance.mTaskQueue.isEmpty()) {
        sInstance.mTaskThreadPool.execute(sInstance.mTaskQueue.poll());
        Log.d("size after start", Integer.toString(sInstance.mTaskQueue.size()));
    } else
        Log.d("queue empty", "yes");
        return;
}
}

在另一个班级我有一个按钮,

假设每次我单击该按钮时,它都会按顺序调用:

  • TaskManager.getinstance().addTask(task)
  • TaskManager.getinstance().startTask();

所以我点击这个按钮一次,一切看起来都很正常,

但是如果我在所有任务完成后再次点击它,

Log.d("queue empty", "yes");将被执行,

我的问题是,我真的不明白这个单例中的BlockingQueue会发生什么,谁能解释一下?谢谢你

4

2 回答 2

1

我不知道具体在 Android 上的这一点,但从标准 Java 文档看来,您使用BlockingQueueandThreadPoolExecutor不正确。您不应该BlockingQueue直接将任务添加到。该类的类文档的“队列维护”部分ThreadPoolExecutor和该方法的文档getQueue()表明您不应与队列交互。

相反,您应该使用界面submit()上的方法添加任务。ExecutorService这将使任务排队并在线程可用时立即开始执行。 是一篇带有更多示例的文章。

要修复,请删除该addTask()方法并修改startTask()为以下内容:

public Future<Void> startTask(Runnable task) {
    return mTaskThreadPool.submit(task);
}

这也将允许您通过返回的 Future 取消任务。取消任务调用Future::cancel(true)

于 2013-09-24T04:57:30.833 回答
0

显然在完成所有任务之后,

ThreadPool 仍然处于活动状态,并将立即获取所有给定的新任务,这些新任务已添加到 TaskQueue,

它会自动使队列为空,

如果给定任务超过MAXIMUM_POOL_SIZE可用线程,它将再次开始排队任务......

于 2013-09-24T04:50:05.887 回答