Java – ThreadPoolExecutor: get the specific runnable being executed
I am using ThreadPoolExecutor to execute multiple long-running tasks in the background. The pool size of ThreadPoolExecutor is 4. Therefore, when more than 4 tasks are added, they are pushed to the queue. When one of the 4 tasks is completed, a task is executed from the queue for execution
I want to know if there is a way to access the runnable objects that are currently executing but not in the queue, that is, the first four tasks
Purpose: I want to get the current status of the task at any given point, in mthreadpoolexecutor With the help of getqueue (), I am accessing the tasks queued and ready to execute. Please advise me to access the tasks currently executing, so that I can attach and delete the listener / handler on it when necessary
My runnable class:
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());
}
}
In the task progress list view:
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);
}
In videouploadmanager, I have the following methods to return the runnable object. Here I need help so that I can return the currently executing task
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;
}
Solution
The best way is to expose a synchronization variable that contains information about the currently executing task
public MyTask implements Runnable {
private String id;
private Map<String,MyTask> mapTasks;
public MyTask(String id,Map<String,MyTask> mapTasks) {
this.id = id;
this.mapTasks = mapTasks;
}
public void run() {
synchronized(mapTasks) {
mapTasks.put(id,this);
}
...
synchronized(mapTasks) {
mapTasks.remove(id);
}
}
}
// Create a map of tasks
Map<String,MyTask> mapTasks = new HashMap<String,MyTask>();
// How to create tasks
MyTask myTask1 = new MyTask("task1",mapTasks);
MyTask myTask2 = new MyTask("task2",mapTasks);
executorService.execute(myTask1);
executorService.execute(myTask2);
....
And print the list of currently executing tasks:
public void printCurrentExecutingTasks(Map<String,MyTask> tasks) {
for (String id: tasks.keySet()) {
System.out.println("Executing task with id: " + id);
}
}
