如何同步处理Java"作业"?

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)

这个问题:

  1. 我们会排队并发请求而不会返回错误消息(我们想要这样做)
  2. 如果JobA想要将消息写入队列以异步处理,我们如何确保当通过另一种方法从队列中读取消息时JobA,该方法将能够Global.lock在另一个JobA启动实例之前获取锁定?

有关更好方法的任何建议吗?

Bri*_*new 8

您是否考虑过使用SingleThreadExecutor?顾名思义,它使用单个线程来执行Callables(类似于Runnables - 请参阅doc),从而满足您对同步处理的要求.使用java.util.concurrent可用的类将极大地简化您的线程代码.

要在另一个作业运行时提交作业并生成错误时处理该方案,请设置有界队列和拒绝处理程序.有关ThreadPoolExecutor.setRejectedExecutionHandler()的详细信息,请参阅本页和8.3.2/8.3.3节.

  • 然后使用最大长度为1的有界队列并配置为抛出异常而不是阻塞. (2认同)

Mik*_*e Q 7

听起来你需要的是一个独占锁,你可以避免在尝试获取锁时阻塞.

幸运的是,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.