0

这个问题与我在 Java 并发主题中的作业有关。我的任务是生成新线程并通过给定的concurrencyFactor. 也就是说,继续调度新线程,直到活动线程数小于或等于concurrencyFactor。如果活动线程数等于concurrencyFactor,程序将等待活动线程数减少到concurrencyFactor - 1并创建一个新线程。

作为第一种方法,我正在使用ExecutorService并创建一个新的固定池Executors.newFixedThreadPool(concurrencyFactor);,每当我的方法被调用时,我只是向这个池提交一个新的可运行文件。逻辑代码如下:

    private final ExecutorService fixedPoolExecutor = Executors.newFixedThreadPool(concurrencyFactor);
    public void handleRequest(final RequestHandler handler) {
    if (handler == null) throw new IllegalArgumentException("Handler cannot be null");
    fixedPoolExecutor.submit(new Runnable() {
        @Override
        public void run() {
            handler.serviceRoutine();
        }
      });
    }

现在,第二部分要求我实现相同的目标,但不使用执行器。我想到了以下两种方法:
1)使用countDownLatch但这个锁存器会等待(即latch.await())直到activeCount变成0。我只想等到倒计时变成concurrencyFactor - 1.
2)使用ThreadGroup并等待直到threadGroup.activeCount() < concurrencyFactor。但是,这种方法的问题是如何让传入的请求等到条件 threadGroup.activeCount() < concurrencyFactor满足?我为这种方法使用了以下代码:

    private final Lock lock = new ReentrantLock();
    private final ThreadGroup threadGroup = new ThreadGroup("myGroup");
    public void handleRequest(final RequestHandler handler) {
    if (handler == null) throw new IllegalArgumentException("Handler cannot be null");
    lock.lock();
    try {
        while (threadGroup.activeCount() >= concurrencyFactor) {

        }
        Thread t = new Thread(threadGroup, new Runnable() {
            @Override
            public void run() {
                handler.service();
            }
        });
        t.start();
    } finally {
        lock.unlock();
    }        
   }

我可以在第二种方法中用一些等待条件替换空白的 while 循环吗?

对上述方法的任何建议或对任何新方法的建议将不胜感激。

4

1 回答 1

1

我建议使用Sempahore. 信号量将表示仍允许启动的线程数。最初,它持有等于配置的并发因子的许可。

在开始一个新线程之前,handleRequest 方法需要从信号量中获取一个许可。启动的线程应该在完成后再次允许释放。

示例代码:

private final ThreadGroup threadGroup = new ThreadGroup("myGroup");
private final Semaphore concurrencyFactor = new Semaphore(CONCURRENCY_FACTOR);

public void handleRequest(final RequestHandler handler) throws InterruptedException {
    if (handler == null) throw new IllegalArgumentException("Handler cannot be null");

    concurrencyFactor.acquire(); // Get permit

    Thread t = new Thread(threadGroup, new Runnable() {
        @Override
        public void run() {
            try {
                handler.service();
            } finally {
                concurrencyFactor.release(); // make sure to release permit
            }
        }
    });
    t.start();
}

(您可能希望以不同的方式处理可能的中断)

于 2017-04-19T17:38:12.617 回答