I have class which implements Runnable
public class MyRunnable implements Runnable {
private long RID = <SOME_LONG_ID_VALUE>;
public long getRID() { return this.RID; }
public void run {
System.out.println("HAI!");
}
}
Is there a way to "route" tasks inside ThreadPoolExecutor
by RID
field ( i mean, if thread N 3 runs Runnable with RID = 1
, then next tast with RID = 1
must be executed by thread N 3 (if it's alive))
Thank you.
As I understand, for each RID you have an execution context and you want to execute all MyRunnable
objects serially against that context.
Your mistake is that you try to link that context to a thread. Better represent that context by an Actor. You can use widely known Actor frameworks like Akka, but for your purpose, simple Actor implementation would work.
EDIT:
Another point of view: since the Actor implementation has the only interface method execute
, it can be considered as a serial executor, running submitted tasks serially. And since it has no own threadpool but uses another executor, shared between all Actors, it can be called a Secondary Executor.
Well I dont think to avoid race condition's (as mentioned in your comments) it would help in any way. Todo:
If Thread N3 does not exists no longer, ThreadPoolExecutor must create new thread with "id" 3. If thread is busy, this task must not be executed until thread will be fre
ThreadPoolExecutor
does thread management for you. To do the above, it is impossible to do it with the existing library, you probably will have to create your own to do it. If your logic and thread safety is dependent upon RID
, than I will rather recommend using a Map of RID and ReentrantLock, somethign like this:
ConcurrentHashMap<Long, ReentrantLock> map = new ConcurrentHashMap<Long, ReentrantLock>();
public synchornized ReentrantLock getLock(Long id){
ReentrantLock lock = map.get(id);
if(lock!=null)
return lock;
else{
map.put(id, new ReentrantLock());
}
In your Runnable
, you can then get the lock
to the desired and synchronize accordingly.
IMHO using thread-id of thread pool for synchronization is a very bad Idea. Life many times can be much simpler.
Use an array of executor services running one thread each. Then assign the tasks according to the modulus %
of the ID (either the raw ID assuming it is long/int or the hash code) relative to some desired max size and use that result as the new ID so that way you can have a balance between ending up with way too many executor service objects while still getting a good amount of concurrency in the processing.
Original idea from answer by h22 here: Thread pool that binds tasks for a given ID to the same thread