Java - 使用 ReentrantLock 异步运行作业?

发布于 2024-10-18 08:09:10 字数 1053 浏览 3 评论 0原文

下面的代码允许我们运行一个作业,同时使用ReentrantLock确保一次只能运行一个作业。

有没有办法修改此代码以异步运行 job.call() 并在启动线程之前将 MyConcurrentJobException 返回给客户端?

我们尝试将 try/catch/finally 块包装在一个新的 Thread 中,但是 unlocklock 必须发生在同一个线程中,所以我们得到一个IllegalMonitorException

??

final static Lock lock = new ReentrantLock();

public Object runJob(String desc, Callable job, boolean wait) {
    logger.info("Acquiring lock");
    if (!lock.tryLock()) {
        throw new MyConcurrentJobException();
    }

    activeJob = new JobStatus(desc);
    logger.info("Lock acquired");

    try {
        return job.call();
    } catch (MarginServiceAssertionException e) {
        throw e;
    } catch (MarginServiceSystemException e) {
        throw e;
    } catch (Exception e) {
        throw new MarginServiceSystemException(e);
    } finally {
        activeJob = null;
        logger.info("Releasing lock");
        lock.unlock();
        logger.info("Lock released");
    }
}

The code below allows us to run a job while ensuring that only one job at a time can run by using ReentrantLock.

Is there any way to modify this code to run job.call() asynchronously and to return the MyConcurrentJobException to the client prior to starting the thread?

We tried wrapping the try/catch/finally block in a new Thread but the unlock and lock have to happen in the same thread so we get an IllegalMonitorException

??

final static Lock lock = new ReentrantLock();

public Object runJob(String desc, Callable job, boolean wait) {
    logger.info("Acquiring lock");
    if (!lock.tryLock()) {
        throw new MyConcurrentJobException();
    }

    activeJob = new JobStatus(desc);
    logger.info("Lock acquired");

    try {
        return job.call();
    } catch (MarginServiceAssertionException e) {
        throw e;
    } catch (MarginServiceSystemException e) {
        throw e;
    } catch (Exception e) {
        throw new MarginServiceSystemException(e);
    } finally {
        activeJob = null;
        logger.info("Releasing lock");
        lock.unlock();
        logger.info("Lock released");
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

怎言笑 2024-10-25 08:09:10

您可以使用Semaphore代替ReentrantLock,它的许可不与线程绑定。

像这样的事情(不确定在异步情况下您想如何处理 job.call() 的结果):

final static Semaphore lock = new Semaphore(1);

public void runJob(String desc, Callable job, boolean wait) {
    logger.info("Acquiring lock");
    if (!lock.tryAcquire()) {
        throw new MyConcurrentJobException();
    }

    startThread(new Runnable() {
        public void run() {
            try {
                job.call();
            } finally {
                lock.release();
            }
        }
    });    
}

You can use Semaphore instead of ReentrantLock, its permits are not bound to thread.

Something like this (not sure what you want to do with the result of job.call() in the asynchronous case):

final static Semaphore lock = new Semaphore(1);

public void runJob(String desc, Callable job, boolean wait) {
    logger.info("Acquiring lock");
    if (!lock.tryAcquire()) {
        throw new MyConcurrentJobException();
    }

    startThread(new Runnable() {
        public void run() {
            try {
                job.call();
            } finally {
                lock.release();
            }
        }
    });    
}
小嗲 2024-10-25 08:09:10

我认为我完全误解了,因为异步执行某些操作时阻塞和等待对我来说没有太大意义,除非可以在调用线程上取得一些进展。

你能做这样的事情吗:

final static Lock lock = new ReentrantLock();
final static ExecutorService service = Executors.newThreadPoolExecutor();
public Object runJob(String desc, Callable job, boolean wait) {
    logger.info("Acquiring lock");
    if (!lock.tryLock()) {
        throw new MyConcurrentJobException();
    }

    activeJob = new JobStatus(desc);
    logger.info("Lock acquired");

    try {
        Future<?> future = service.submit(job);
        // This next line will block until the job is finished
        // and also will hold onto the lock.
        boolean finished = false;
        Object o = null;
        while(!finished) {
            try {
                o = future.get(300, TimeUnit.MILLISECONDS);
                finished = true;
            catch(TimeOutException e) {
                // Do some periodic task while waiting
                // foot.tapLots();
            }
         }
         if (o instanceof MarginServiceAssertionException) {
             throw ((MargineServiceAssertionException)o);
         } else if (o instanceof MargineServiceSystemException) {
             throw ((MarginServiceSystemException)o);
         } else if (o instanceof Exception) {
             throw new MarginServiceSystemException(e);
         }
    } catch (... InterruptedException e) { /// catch whatever exceptions throws as part of this
       /// Whatever needs to be done.
    } finally {
        activeJob = null;
        logger.info("Releasing lock");
        lock.unlock();
        logger.info("Lock released");
    }
}

I think I am misunderstanding completely because to block and wait while doing something asynchronously doesn't make too much sense to me unless some progress can be made on the invoking thread.

Could you do something like this:

final static Lock lock = new ReentrantLock();
final static ExecutorService service = Executors.newThreadPoolExecutor();
public Object runJob(String desc, Callable job, boolean wait) {
    logger.info("Acquiring lock");
    if (!lock.tryLock()) {
        throw new MyConcurrentJobException();
    }

    activeJob = new JobStatus(desc);
    logger.info("Lock acquired");

    try {
        Future<?> future = service.submit(job);
        // This next line will block until the job is finished
        // and also will hold onto the lock.
        boolean finished = false;
        Object o = null;
        while(!finished) {
            try {
                o = future.get(300, TimeUnit.MILLISECONDS);
                finished = true;
            catch(TimeOutException e) {
                // Do some periodic task while waiting
                // foot.tapLots();
            }
         }
         if (o instanceof MarginServiceAssertionException) {
             throw ((MargineServiceAssertionException)o);
         } else if (o instanceof MargineServiceSystemException) {
             throw ((MarginServiceSystemException)o);
         } else if (o instanceof Exception) {
             throw new MarginServiceSystemException(e);
         }
    } catch (... InterruptedException e) { /// catch whatever exceptions throws as part of this
       /// Whatever needs to be done.
    } finally {
        activeJob = null;
        logger.info("Releasing lock");
        lock.unlock();
        logger.info("Lock released");
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文