I am using ThreadPoolExecutor
to execute multiple long running tasks in background, pool size of ThreadPoolExecutor
is 4 so when more than 4 task are being added they are pushed on to queue and when one of 4 tasks gets complete one task is poped from queue for execution.
I want to know is there any way to access object of Runnable
that are currently being executed and not in queue, i.e first 4 tasks.
Aim: I want to do this to get current status of task at any given point, with the help of mThreadPoolExecutor.getQueue()
I am accessing tasks being queued and ready to execute, please suggest me way to access tasks those are currently being executed so that I can attach and remove listener/handler on it when ever required.
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 Task progress list view holder:
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 following method to return Runnable
object, Here I want help so that I can return tasks being currently executed.
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;
}
The best way is to expose a synchronized variable holding the informations on currently executing tasks.
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);
}
try {
...
} finally {
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 to print the list of tasks currently in execution:
public void printCurrentExecutingTasks(Map<String, MyTask> tasks) {
for (String id: tasks.keySet()) {
System.out.println("Executing task with id: " + id);
}
}