1

我有实现 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!");
    }
}

有没有办法ThreadPoolExecutorRID字段“路由”内部任务(我的意思是,如果线程 N 3 运行 Runnable with RID = 1,那么下一个 tast withRID = 1必须由线程 N 3 执行(如果它还活着))谢谢。

4

3 回答 3

1

据我了解,对于每个 RID,您都有一个执行上下文,并且您希望MyRunnable针对该上下文连续执行所有对象。

您的错误是您尝试将该上下文链接到线程。更好地由 Actor 表示该上下文。您可以使用广为人知的 Actor 框架,例如 Akka,但出于您的目的,简单的Actor 实现就可以了。

编辑:另一种观点:由于 Actor 实现具有唯一的接口方法execute,因此可以将其视为串行执行器,串行运行提交的任务。而且由于它没有自己的线程池,而是使用另一个执行器,在所有 Actor 之间共享,因此可以称为辅助执行器。

于 2013-07-23T14:38:26.333 回答
0

好吧,我认为避免竞争条件(如您的评论中所述)无论如何都会有所帮助。去做:

如果线程 N3 不再存在,则 ThreadPoolExecutor 必须创建新线程,“id”为 3。如果线程忙,则在线程空闲之前不能执行此任务

ThreadPoolExecutor为你做线程管理。要做到以上,用现有的库是不可能的,你可能必须创建自己的库来做到这一点。如果您的逻辑和线程安全依赖于RID,那么我宁愿推荐使用 RID 和 ReentrantLock 的 Map,如下所示:

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

在您的Runnable中,您可以得到lock所需的并相应地同步。

恕我直言,使用线程池的线程 ID 进行同步是一个非常糟糕的主意。生活很多时候可以简单得多。

于 2013-07-23T13:45:57.210 回答
0

使用一组执行器服务,每个服务运行一个线程。然后根据%ID 的模数(假设它是 long/int 的原始 ID 或哈希码)相对于某个所需的最大大小分配任务,并将该结果用作新 ID,这样您就可以在两者之间取得平衡最终得到太多的执行器服务对象,同时在处理过程中仍然获得了大量的并发性。

来自 h22 回答的原始想法:将给定 ID 的任务绑定到同一线程的线程池

于 2018-08-29T16:45:31.337 回答