【发布时间】:2017-06-23 14:05:42
【问题描述】:
我正在使用ThreadPoolExecutor 在后台执行多个长时间运行的任务,ThreadPoolExecutor 的池大小为 4,因此当添加超过 4 个任务时,它们被推送到队列中,并且当 4 个任务之一完成时任务从队列中弹出执行。
我想知道有什么方法可以访问当前正在执行且不在队列中的Runnable 对象,即前 4 个任务。
目标:我想在任何给定点获取任务的当前状态,在mThreadPoolExecutor.getQueue() 的帮助下我正在访问正在排队并准备执行的任务,请建议我访问当前正在执行的任务的方法执行,以便我可以在需要时附加和删除侦听器/处理程序。
我的 Runnable 类:
public class VideoFileUploadRunner implements Runnable {
private final VideoFileSync mVideoFileSync;
private final DataService dataService;
private Handler handler;
public VideoFileUploadRunner(VideoFileSync videoFileSync, DataService dataService) {
this.mVideoFileSync = videoFileSync;
this.dataService = dataService;
}
public int getPK()
{
return mVideoFileSync.get_idPrimaryKey();
}
public void setHandler(Handler handler) {
this.handler = handler;
}
@Override
public void run() {
try {
if (mVideoFileSync.get_idPrimaryKey() < 0) {
addEntryToDataBase();
}
updateStatus(VideoUploadStatus.IN_PROGRESS);
FileUploader uploader = new FileUploader();
updateStatus(uploader.uploadFile(mVideoFileSync.getVideoFile()));
} catch (Exception e) {
updateStatus(VideoUploadStatus.FAILED);
e.printStackTrace();
}
}
private void addEntryToDataBase() {
int pk = dataService.saveVideoRecordForSync(mVideoFileSync);
mVideoFileSync.set_idPrimaryKey(pk);
}
private void updateStatus(VideoUploadStatus status) {
if (handler != null) {
Message msg = new Message();
Bundle b = new Bundle();
b.putString(AppConstants.Sync_Status, status.toString());
msg.setData(b);
handler.sendMessage(msg);
}
dataService.updateUploadStatus(mVideoFileSync.get_idPrimaryKey(), status.toString());
}
}
在任务进度列表视图中:
public void setData(VideoFileSync fileSync) {
tvIso.setText(fileSync.getVideoFile().getISO_LOOP_EQUP());
tvUnit.setText(fileSync.getVideoFile().getUnit());
tvName.setText(fileSync.getVideoFile().getLocalPath());
tvStatus.setText(fileSync.getCurentStatus().toString());
addHandleForUpdate(fileSync);
}
private void addHandleForUpdate(VideoFileSync fileSync) {
Handler.Callback callBack = new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
if(msg.getData()!=null)
{
tvStatus.setText(msg.getData().getString(AppConstants.Sync_Status));
}
return false;
}
};
mHadler = new Handler(Looper.getMainLooper(),callBack);
VideoFileUploadRunner runner = VideoUploadManager.getInstance().getRunnerForSyncFile(fileSync);
if(runner!=null)
runner.setHandler(mHadler);
}
在 VideoUploadManager 中,我有以下方法返回 Runnable 对象,在这里我需要帮助,以便我可以返回当前正在执行的任务。
public synchronized VideoFileUploadRunner getRunnerForSyncFile(VideoFileSync fileSync) {
Iterator<Runnable> itr = mThreadPoolExecutor.getQueue().iterator();
while (itr.hasNext()) {
VideoFileUploadRunner runner = (VideoFileUploadRunner) itr.next();
if (runner.getPK() == fileSync.get_idPrimaryKey()) {
return runner;
}
}
return null;
}
【问题讨论】:
-
这样我就可以在需要时在其上附加和删除侦听器/处理程序。你能详细说明你的意思吗?
-
我正在开发移动应用程序,其中我有一个屏幕来显示任务的当前状态,用户可以关闭应用程序并返回检查状态,所以当用户在屏幕上时,我想将处理程序附加到可运行对象
-
而不是从 runnable 的外部尝试通过 executor 找到 runnable 并将侦听器附加到它。从 runnables run 方法内部,绑定到外部侦听器并在结束时取消绑定方法。因此,您可以在 runnable 中发布您的事件、订阅和取消订阅,并且只有当前处于活动状态的 runnable 才会发布它们的更新。
-
使用
FutureTask可能会有所帮助。看看stackoverflow.com/questions/30789402/… -
@DCoder 查看我的回答。您可以使用 ThreadFactory 为您保存 Runnable 引用。请留下评论以进一步澄清。
标签: java android multithreading runnable threadpoolexecutor