自定義 Runnables 而不是 Callables
檢查我們的執行緒何時完成而不阻塞等待從 Callable 恢復 Future 物件的執行緒的另一個好習慣是為 Runnables 建立我們自己的實現,並將其與 execute()
方法一起使用。
在下一個示例中,我展示了一個使用內部回撥實現 Runnable 的自定義類,允許我們知道 runnables 何時完成並稍後在 ThreadPool 中使用它:
public class CallbackTask implements Runnable {
private final Runnable mTask;
private final RunnableCallback mCallback;
public CallbackTask(Runnable task, RunnableCallback runnableCallback) {
this.mTask = task;
this.mCallback = runnableCallback;
}
public void run() {
long startRunnable = System.currentTimeMillis();
mTask.run();
mCallback.onRunnableComplete(startRunnable);
}
public interface RunnableCallback {
void onRunnableComplete(long runnableStartTime);
}
}
這是我們的 ThreadExecutor 實現:
public class ThreadExecutorExample implements ThreadExecutor {
private static String TAG = "ThreadExecutorExample";
public static final int THREADPOOL_SIZE = 4;
private long mSubmittedTasks;
private long mCompletedTasks;
private long mNotCompletedTasks;
private ThreadPoolExecutor mThreadPoolExecutor;
public ThreadExecutorExample() {
Log.i(TAG, "[ThreadExecutorImpl] Initializing ThreadExecutorImpl");
Log.i(TAG, "[ThreadExecutorImpl] current cores: " + Runtime.getRuntime().availableProcessors());
this.mThreadPoolExecutor =
(ThreadPoolExecutor) Executors.newFixedThreadPool(THREADPOOL_SIZE);
}
@Override
public void execute(Runnable runnable) {
try {
if (runnable == null) {
Log.e(TAG, "[execute] Runnable to execute cannot be null");
return;
}
Log.i(TAG, "[execute] Executing new Thread");
this.mThreadPoolExecutor.execute(new CallbackTask(runnable, new CallbackTask.RunnableCallback() {
@Override
public void onRunnableComplete(long RunnableStartTime) {
mSubmittedTasks = mThreadPoolExecutor.getTaskCount();
mCompletedTasks = mThreadPoolExecutor.getCompletedTaskCount();
mNotCompletedTasks = mSubmittedTasks - mCompletedTasks; // approximate
Log.i(TAG, "[execute] [onRunnableComplete] Runnable complete in " + (System.currentTimeMillis() - RunnableStartTime) + "ms");
Log.i(TAG, "[execute] [onRunnableComplete] Current threads working " + mNotCompletedTasks);
}
}));
}
catch (Exception e) {
e.printStackTrace();
Log.e(TAG, "[execute] Error, shutDown the Executor");
this.mThreadPoolExecutor.shutdown();
}
}
}
/**
* Executor thread abstraction created to change the execution context from any thread from out ThreadExecutor.
*/
interface ThreadExecutor extends Executor {
void execute(Runnable runnable);
}
我做了這個例子來檢查我的執行緒的速度,以毫秒為單位執行它們,而不使用 Future。你可以使用此示例並將其新增到你的應用程式以控制併發任務的工作,以及已完成/已完成的任務。檢查所有時刻,執行該執行緒所需的時間。