Java 这个关于信号量的代码片段是必要的吗?

Java 这个关于信号量的代码片段是必要的吗?,java,concurrency,semaphore,Java,Concurrency,Semaphore,下面是Java并发实践中的代码,展示了如何在工作队列已满时通过使用信号量来限制任务注入速率,从而使execute阻塞。信号量等于池大小加上您希望允许的排队任务数 public class BoundedExecutor { private final Executor exec; private final Semaphore semaphore; public BoundedExecutor(Executor exec, int bound) { thi

下面是Java并发实践中的代码,展示了如何在工作队列已满时通过使用
信号量
来限制任务注入速率,从而使execute阻塞。信号量等于池大小加上您希望允许的排队任务数

public class BoundedExecutor {
    private final Executor exec;
    private final Semaphore semaphore;
    public BoundedExecutor(Executor exec, int bound) {
        this.exec = exec;
        this.semaphore = new Semaphore(bound);
    }
    public void submitTask(final Runnable command)
            throws InterruptedException {
        semaphore.acquire();
        try {
            exec.execute(new Runnable() {
                public void run() {
                    try {
                        command.run();
                    } finally {
                    semaphore.release();
                    }
                }
            });
        } catch (RejectedExecutionException e) {
            semaphore.release();
        }
    }
}
我的问题是关于

catch(RejectedExecutionException e){semaphore.release();}

当我们有
semaphore.acquire()时,它不是没有必要吗以上


如果工作队列已满,则应阻止“semaphore.acquire”,并且不会出现
拒绝执行异常

文档中说,如果无法接受此任务执行,则
会抛出拒绝执行异常
。如果由于任何原因无法接受任务,您需要确保信号量被释放。

如果无法接受任务,执行者可以抛出
RejectedExecutionException
。如果发生这种情况,则意味着信号量已被获取,但执行者决定它无法接受任务

此行为取决于执行器的实现,因此它独立于成功调用
acquire()
,如果确实发生,则必须释放信号量以指示新任务有可用的插槽


理想情况下,该方法应返回true或false,以指示是否发生了这种情况。

即使您假设执行者永远不会拒绝您的请求(例如,因为您认为界限低于执行者的池大小+队列限制),也最好不要依赖您的假设。即使您的假设是错误的,上述代码也将正常工作,如果您的假设是正确的,则不会产生任何负面影响


目前,上面的代码没有在执行器上设置任何边界,只在信号量上设置边界,因此当然可以选择一个高于执行器将接受的边界。

我认为您混淆了内部执行器(通过构造函数中的参数传递)和外部执行器(BoundedExecutor)。即使BoundedExecutor类的名称中有executor单词,并且有一个提交任务的方法,它也没有实现
executor
接口

这是一种装饰类。它所做的是提供普通执行者提供的功能,但限制可以提交的任务数量


您提到的异常是由内部执行器的
execute
方法引发的。因为临界部分可以抛出异常,所以需要释放finally子句中的锁。否则,您将错误地计算提交失败的次数。

如果线程获得锁,但随后遇到异常,例如,在
命令.run()
上,它需要释放锁。否则,其他线程将无法获取该特定锁。