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