Java 是否有一种方法可以基于属性将可运行任务分组到同一线程中,以便具有相同属性的可运行任务同步运行?
假设我有一个Java 是否有一种方法可以基于属性将可运行任务分组到同一线程中,以便具有相同属性的可运行任务同步运行?,java,multithreading,Java,Multithreading,假设我有一个ExecutorService,我用它来运行作业对象,这个类扩展了Runnable。我希望我的Job对象并行运行,但同时运行两个Job对象和同一个Job.getTypeId()可能会带来不利影响。因此,如果我要提交一个作业,我必须首先确保没有一个作业运行相同的作业。getTypeId(),如果有,它需要排队等待,直到完成 这是一个边缘案例:具有相同TypeId的作业通常不会在同一时间提交,但如果提交,我需要能够正确处理。虽然它是一个边缘案例,但它是一个重要的用例 我想到的最好的主意是
ExecutorService
,我用它来运行作业
对象,这个类扩展了Runnable
。我希望我的Job
对象并行运行,但同时运行两个Job
对象和同一个Job.getTypeId()
可能会带来不利影响。因此,如果我要提交一个作业,我必须首先确保没有一个作业运行相同的作业。getTypeId(),如果有,它需要排队等待,直到完成
这是一个边缘案例:具有相同TypeId的作业通常不会在同一时间提交,但如果提交,我需要能够正确处理。虽然它是一个边缘案例,但它是一个重要的用例
我想到的最好的主意是,对ExecutorServices
进行某种Collection
的配置,类似于Executors.newSingleThreadedExecutor
,比如HashMap
,其中我的TypeId
是与单线程执行器关联的键。保持这一点,虽然完全可能,但感觉这比替代解决方案更麻烦。问题是,可能会得到几个需要同步运行的作业
,但之后再也看不到TypeId
。我需要实现一种方法来清除所有在一段时间内没有使用过的单线程执行器,以避免我的单线程执行器列表中出现内存泄漏
我只是想知道我是否在试图解决一个已经解决的问题
是否已经有一个执行模型可以解决我的问题?是否有一种方法可以配置线程池,例如,使用线程名中的my
Job.getTypeId()
创建一个线程,并在提交时将所有具有相同TypeId
的Job
对象分配给同一个线程 我的一位同事给我指出了一个很好的解决方案,有人可以随意给出他们认为更好的其他解决方案。解决方案是利用Guava的条带锁来允许线程锁定特定的JobTypeId。这意味着可以为同一JobTypeId创建两个线程,但首先创建的线程将锁定该Id,而另一个线程将被阻止运行,直到锁再次可用。具有相同TypeId的作业不在同一线程上运行,但它们都在同一条带上运行
分条文档:
锁定文档:
代码:
公共类JobRunner实现了{
私人最终条纹锁;
私有最终int-typeId;
public JobRunner(条带锁,int-typeId){
this.locks=锁;
this.typeId=typeId;
}
公开募捐{
lock=locks.get(typeId);
lock.lock()//这会阻止线程,直到锁变为可用(如果它还没有可用)
嫁妆
}
私房{
//巴士,做好你的事!
}
}
只要所有的JobRunner都共享相同的
Striped
singleton,一切都应该很好 那么两个具有相同类型id的作业可以在不同的线程中执行,只要它们不是并行执行的?是否有一组固定的可能类型ID,或者可以有任意多个类型ID?这是正确的,不要求它们在同一个线程中,只要求它们不在同一时间运行。不幸的是,没有一组可能的id。TypeId实际上代表为其运行作业的客户机(公司),客户机来来去去,其唯一id也是如此。我们可以并行运行多个作业,只要每个客户端一次运行的作业不超过1个。@JHixson newSingleThreadExecutor似乎解决了错误的问题。一个正常的执行器服务就足够了。在我看来,您需要的是一个HashMap
,其中SpecialSynchQueue
是一个队列,它包含相同类型的作业,将此类型的新作业排入队列,并在此类型的前一个作业完成执行时提交下一个作业。为此,您必须将每个作业包装到另一个类中,该类在作业完成后立即插入队列,以便队列唤醒并最终将同一类型的下一个作业提交给executor。这有什么意义吗?
public class JobRunner implements Runner {
private final Striped<Lock> locks;
private final int typeId;
public JobRunner(Striped<Lock> locks, int typeId){
this.locks = locks;
this.typeId = typeId;
}
public void run() {
lock = locks.get(typeId);
lock.lock() //This blocks the thread untill the lock becomes available if it wasn't already
doWork()
}
private void doWork(){
//Bus, do your stuff!
}
}