Java线程睡眠

时间:2011-06-20 15:02:20

标签: java multithreading

我有一个主要的for循环,它将请求发送到外部系统。外部系统可能需要几秒钟甚至几分钟才能回复 此外,如果请求数达到MAX_REQUESTS,则当前的for-loop应该休眠几秒钟。

这是我的情景。让我们说主要for-loop进入睡眠时间为5秒,因为它已达到MAX_REQUESTS。然后说来自callExternalSystem()的先前外部请求返回。当前处于SLEEP状态的主要for循环线程会发生什么?是否会中断并继续处理或继续休眠?

for(...){
  ...
  while(numRequestsProcessing > MAX_REQUESTS){
     Thread.sleep(SLEEP_TIME);
  }
  ...
 callExternalSystem();

}

提前致谢。

3 个答案:

答案 0 :(得分:5)

除非你有一些代码来打断睡眠线程,否则它会继续睡眠直到所需的时间结束。如果您不希望这种情况发生,您可以使用wait() / notify()而不是sleep(),以便另一个线程可以按顺序通知对象主线程处于休眠状态唤醒它。那依赖于 另一个线程来注意到外部系统已经做出响应 - 当然 - 你不知道如何得到回复。

编辑:听起来你应该使用Semaphore。每次主线程想要发出请求时,它都会获得许可。每次有响应时,都会发布许可证。然后,您只需要设置尽可能多的许可,就像您想要并发请求一样。如果您希望能够在主线程中指定超时,请使用tryAcquire - 但如果您已经拥有尽可能多的未完成请求,请考虑您想要做什么。

答案 1 :(得分:3)

我会使用java.util.concurrent.Executors来创建一个包含MAX_REQUESTS个线程的线程池。为您一次发送的许多请求创建一个java.util.concurrent.CountDownLatch。将锁存器传递给发出请求的Runnables,它们在完成时调用锁存器上的countDown()。然后主线程在锁存器上调用await(timeout)。我还建议使用“Java Concurrency in Practice”这本书。

答案 2 :(得分:1)

一种方法是使用ThreadPoolExecutor,只要没有空闲线程就会阻塞。

ThreadPoolExecutor executor = new ThreadPoolExecutor(MAX_REQUESTS, MAX_REQUESTS, 60, TimeUnit.SECONDS, new SynchronousQueue<Runnable>(), new RejectedExecutionHandler() {
    @Override
    public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
        try {
            executor.getQueue().offer(r, Long.MAX_VALUE, TimeUnit.NANOSECONDS);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
});
for(int i=0;i<LOTS_OF_REQUESTS;i++) {
    final int finalI = i;
    executor.submit(new Runnable() {
        @Override
        public void run() {
            request(finalI);
        }
    });
}

另一种方法是让任务生成自己的请求。这样,每次线程并发时都会生成一个新请求。

ExecutorService executor = Executors.newFixedThreadPool(MAX_REQUESTS);
final AtomicInteger counter = new AtomicInteger();
for (int i = 0; i < MAX_REQUESTS; i++) {
    executor.submit(new Runnable() {
        @Override
        public void run() {
            int i;
            while ((i = counter.getAndIncrement()) < LOTS_OF_REQUESTS)
                request(i);
        }
    });
}