Mar*_*eon 1 java concurrency synchronization
我们有一套行动或"工作",我们希望一次发生一次(不同时发生).即:当B发生时,作业A不会发生,并且您不能同时运行两个C作业.
如果线程尝试同时运行作业,则应该收到错误.我们不应该只是排队请求.
某些作业以异步方式发生,用户发出请求,我们返回状态消息和id,然后在服务器上异步处理作业.
我们正在寻找有关如何处理此方案的建议.
一种选择是锁定共享对象:
public class Global {
public static final Object lock = new Object();
}
public class JobA {
public void go() {
synchronized(Global.lock) {
//Do A stuff
}
}
}
public class JobB {
public void go() {
synchronized(Global.lock) {
//Do B stuff
}
}
}
Run Code Online (Sandbox Code Playgroud)
这个问题:
JobA想要将消息写入队列以异步处理,我们如何确保当通过另一种方法从队列中读取消息时JobA,该方法将能够Global.lock在另一个JobA启动实例之前获取锁定?有关更好方法的任何建议吗?
您是否考虑过使用SingleThreadExecutor?顾名思义,它使用单个线程来执行Callables(类似于Runnables - 请参阅doc),从而满足您对同步处理的要求.使用java.util.concurrent可用的类将极大地简化您的线程代码.
要在另一个作业运行时提交作业并生成错误时处理该方案,请设置有界队列和拒绝处理程序.有关ThreadPoolExecutor.setRejectedExecutionHandler()的详细信息,请参阅本页和8.3.2/8.3.3节.
听起来你需要的是一个独占锁,你可以避免在尝试获取锁时阻塞.
幸运的是,Lock接口有一个tryLock方法,因此您可以执行以下操作.
final Lock lock = new ReentrantLock();
....
void attemptJob( Runnable runnable )
{
if (!lock.tryLock())
throw new ConcurrentJobException();
try
{
runnable.run();
}
finally
{
lock.unlock();
}
}
Run Code Online (Sandbox Code Playgroud)
如果要运行异步,则应将Runnable(或者如果愿意可调用)委派给ExecutorService,并在完成时释放锁.
编辑:例如(加上一些更多的最终声明)
final Lock lock = new ReentrantLock();
final ExecutorService service = Executors.newSingleThreadExecutor();
....
void attemptJob( final Runnable runnable )
{
if (!lock.tryLock())
throw new ConcurrentJobException();
service.execute( new Runnable()
{
public void run()
{
try
{
runnable.run();
}
finally
{
lock.unlock();
}
}
});
}
Run Code Online (Sandbox Code Playgroud)
完成后,不要忘记关闭()ExecutorService.
| 归档时间: |
|
| 查看次数: |
3041 次 |
| 最近记录: |