Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/338.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在循环中调用可中断的阻塞方法_Java_Multithreading_Concurrency - Fatal编程技术网

Java 在循环中调用可中断的阻塞方法

Java 在循环中调用可中断的阻塞方法,java,multithreading,concurrency,Java,Multithreading,Concurrency,这个问题来自Brian Goetz的《Java并发实践》一书中的一个例子,第7章,7.1.3响应中断(第143-144页) 书上说 不支持取消但仍调用可中断阻塞方法的活动必须在循环中调用它们,在检测到中断时重试。在这种情况下,他们应该在本地保存中断状态,并在返回之前将其恢复,如下面的示例所示,而不是在捕获InterruptedException后立即恢复。过早地设置中断状态可能会导致无限循环,因为大多数可中断的阻塞方法会在进入时检查中断状态,如果设置了,则会立即抛出InterruptedExce

这个问题来自Brian Goetz的《Java并发实践》一书中的一个例子,第7章,7.1.3响应中断(第143-144页) 书上说

不支持取消但仍调用可中断阻塞方法的活动必须在循环中调用它们,在检测到中断时重试。在这种情况下,他们应该在本地保存中断状态,并在返回之前将其恢复,如下面的示例所示,而不是在捕获InterruptedException后立即恢复。过早地设置中断状态可能会导致无限循环,因为大多数可中断的阻塞方法会在进入时检查中断状态,如果设置了,则会立即抛出InterruptedException

公共任务getNextTask(阻塞队列){
布尔值=假;
试一试{
while(true){
试一试{
返回队列。take();
}捕捉(中断异常e){
中断=真;
}
}
}最后{
如果(中断)
Thread.currentThread().interrupt();
}
}
我的问题是为什么需要循环


另外,如果queue.take()抛出interruptedException,那么我假设在当前线程上设置了中断标志,对吗?然后,对queue.take()的下一次调用将再次抛出interruptedException,因为当前线程上的上一个中断未被清除,这不会导致无限循环吗?

,因为否则将无法保证按照方法签名的要求返回任务。没有循环,考虑方法:

public Task getNextTask(BlockingQueue<Task> queue) {
  boolean interrupted = false;
  try {
    return queue.take();
  } catch (InterruptedException e) {
    interrupted = true;//No return here, the compiler will complain
  } finally {
    if(interrupted) {
      Thread.currentThread().interrupt();
    }
  }
}
公共任务getNextTask(阻塞队列){
布尔值=假;
试一试{
返回队列。take();
}捕捉(中断异常e){
interrupted=true;//此处不返回,编译器将抱怨
}最后{
如果(中断){
Thread.currentThread().interrupt();
}
}
}

,否则您将无法保证按照方法签名的要求返回任务。没有循环,考虑方法:

public Task getNextTask(BlockingQueue<Task> queue) {
  boolean interrupted = false;
  try {
    return queue.take();
  } catch (InterruptedException e) {
    interrupted = true;//No return here, the compiler will complain
  } finally {
    if(interrupted) {
      Thread.currentThread().interrupt();
    }
  }
}
公共任务getNextTask(阻塞队列){
布尔值=假;
试一试{
返回队列。take();
}捕捉(中断异常e){
interrupted=true;//此处不返回,编译器将抱怨
}最后{
如果(中断){
Thread.currentThread().interrupt();
}
}
}

回答您的第一个问题

My question is why is the loop required?
就在这条线上

       Activities that do not support cancellation but still call interruptible 
blocking methods will have to call them in a loop, retrying when interruption 
is detected.  
     From Java concurrency in Practice 7.1.3
getNextTask方法不支持取消。也就是说,即使线程被中断,它也不会取消它的任务,并将再次重试。请注意,getNextTask方法正在调用一个可中断的阻塞方法queue.take(),该方法引发intteruptedException。getNextTask方法必须处理interruptedException,因为它不支持取消,应该重试。 简单地说,它是一种方法策略,决定要么重试,要么在方法签名中抛出中断的异常

你的第二个问题

Also if queue.take() throws an interruptedException then I am assuming the 
interrupt flag is set on the current thread correct? 
否如果引发中断异常,则重置中断标志

还要注意,在finally块中,线程本身是自中断的(thread.currentThread().interrupt()),因为getNextTask的调用堆栈也可能调用其他可中断的阻塞方法,这些方法通常首先检查当前线程是否已被中断。如果是,则重置中断标志,并显示中断异常 就像下面的一样

Below is the Code from AQS(AbstractQueueSynchronizer) from java

     public final void acquireInterruptibly(int arg) throws InterruptedException {
            if (Thread.interrupted())
                throw new InterruptedException();
            if (!tryAcquire(arg))
                doAcquireInterruptibly(arg);
        }

回答你的第一个问题

My question is why is the loop required?
就在这条线上

       Activities that do not support cancellation but still call interruptible 
blocking methods will have to call them in a loop, retrying when interruption 
is detected.  
     From Java concurrency in Practice 7.1.3
getNextTask方法不支持取消。也就是说,即使线程被中断,它也不会取消它的任务,并将再次重试。请注意,getNextTask方法正在调用一个可中断的阻塞方法queue.take(),该方法引发intteruptedException。getNextTask方法必须处理interruptedException,因为它不支持取消,应该重试。 简单地说,它是一种方法策略,它决定重试或只是在方法签名中抛出中断异常

你的第二个问题

Also if queue.take() throws an interruptedException then I am assuming the 
interrupt flag is set on the current thread correct? 
否如果引发中断异常,则重置中断标志

还要注意,在finally块中,线程本身是自中断的(thread.currentThread().interrupt()),因为getNextTask的调用堆栈也可能调用其他可中断的阻塞方法,这些方法通常首先检查当前线程是否已被中断。如果是,则重置中断标志,并显示中断异常 就像下面的一样

Below is the Code from AQS(AbstractQueueSynchronizer) from java

     public final void acquireInterruptibly(int arg) throws InterruptedException {
            if (Thread.interrupted())
                throw new InterruptedException();
            if (!tryAcquire(arg))
                doAcquireInterruptibly(arg);
        }

因为您已经决定getNextTask不会抛出异常。当
queue.take()
不起作用时,唯一要做的就是四处走动并重试。返回null在道德上等同于抛出异常,而调用代码可能没有为此做好准备。此方法的唯一出路是使用良好的值或RunTimeException。(对我来说似乎有点极端,但毫无疑问这是有道理的。)


实际上,您并没有看到中断标志;它的条件不影响此代码。经过深思熟虑,您可以将其设置为当调用程序确实获得其
任务
(或RunTimeException)时,可以知道有东西试图中断它。(不要将局部变量
interrupted
与线程方法
interrupted()
!)混淆)

,因为您已经决定getNextTask不会抛出异常。当
queue.take()
不起作用时,唯一要做的就是四处走动并重试。返回null在道德上等同于抛出异常,而调用代码可能没有为此做好准备。此方法的唯一出路是使用良好的值或RunTimeException。(对我来说似乎有点极端,但毫无疑问这是有道理的。)

实际上,您并没有看到中断标志;它的条件不影响此代码。你是,深思熟虑,