Java多线程中断机制

 

 

thread中的三个方法:interrupt()、interrupted()、isInterrupted()
1、interrupt()
public void interrupt() {
  if (this != Thread.currentThread())
    checkAccess();
 
  synchronized (blockerLock) {
    Interruptible b = blocker;
    if (b != null) {
    interrupt0();    // Just to set the interrupt flag
    b.interrupt();
    return;
    }
  }
  interrupt0();
  }


/* Some private helper methods */
private native void setPriority0(int newPriority);
private native void stop0(Object o);
private native void suspend0();
private native void resume0();
private native void interrupt0();
 
分两部分看:
(1)第一部分的第8行注释说得很清楚了,interrupt0()方法的作用是"Just to set the interrupt flag",即方法的作用仅仅是设置中断标识位
(2)第二部分的第6行就是interrupt0()方法的原型,由于方法是被native修饰的,很明显这是一个本地方法,是Java虚拟机实现的。
当对一个线程,调用 interrupt() 时,
  • 如果线程处于被阻塞状态(例如处于sleep, wait, join 等状态),那么线程将立即退出被阻塞状态,并抛出一个InterruptedException异常。
  • 如果线程处于正常活动状态,那么会将该线程的中断标志设置为 true。被设置中断标志的线程将继续正常运行,不受影响。
 
 
 
2、isInterrupted()
方法唯一的作用只是测试线程是否已经中断,中断标识位的状态并不受到该方法的影响,看一下Java是如何实现这个方法的:
/**
 * Tests whether this thread has been interrupted. The <i>interrupted
 * status</i> of the thread is unaffected by this method.
 *
 * <p>A thread interruption ignored because a thread was not alive 
 * at the time of the interrupt will be reflected by this method 
 * returning false.
 *
 * @return <code>true</code> if this thread has been interrupted;
 *     <code>false</code> otherwise.
 * @see   #interrupted()
 * @revised 6.0
 */
public boolean isInterrupted() {
return isInterrupted(false);
}

private native boolean isInterrupted(boolean ClearInterrupted);
注意一下第一部分的第2行和第3行,"The interrupted statis of the thread is unaffected by this method",即线程的中断状态不受到这个方法的影响。最终调用的是isInterrupted(boolean ClearInterrupted),这个方法是一个native的,看得出也是Java虚拟机实现的。方法的参数ClearInterrupted,顾名思义,清除中断标识位,这里传递false,明显就是不清除。
 
3、interrupted()
方法的作用是测试当前线程是否已经中断,线程的中断标识位由该方法清除。换句话说,连续两次调用该方法的返回值必定是false。看一下这个方法是如何实现的:
/**
 * Tests whether the current thread has been interrupted. The
 * <i>interrupted status</i> of the thread is cleared by this method. In
 * other words, if this method were to be called twice in succession, the
 * second call would return false (unless the current thread were
 * interrupted again, after the first call had cleared its interrupted
 * status and before the second call had examined it).
 *
 * <p>A thread interruption ignored because a thread was not alive 
 * at the time of the interrupt will be reflected by this method 
 * returning false.
 *
 * @return <code>true</code> if the current thread has been interrupted;
 *     <code>false</code> otherwise.
 * @see #isInterrupted()
 * @revised 6.0
 */
public static boolean interrupted() {
return currentThread().isInterrupted(true);

private native boolean isInterrupted(boolean ClearInterrupted);
而如果一个线程被设置中断标识后,进行了一些处理后选择继续进行任务, 而且这个任务也是需要被中断的,那么当然需要清除标志位了。
 

example

org.springframework.scheduling.concurrent.ExecutorConfigurationSupport
注意代码中Thread.currentThread().interrupt();的用法。
	/**
	 * Perform a shutdown on the underlying ExecutorService.
	 * @see java.util.concurrent.ExecutorService#shutdown()
	 * @see java.util.concurrent.ExecutorService#shutdownNow()
	 * @see #awaitTerminationIfNecessary()
	 */
	public void shutdown() {
		if (logger.isInfoEnabled()) {
			logger.info("Shutting down ExecutorService" + (this.beanName != null ? " '" + this.beanName + "'" : ""));
		}
		if (this.waitForTasksToCompleteOnShutdown) {
			this.executor.shutdown();
		}
		else {
			this.executor.shutdownNow();
		}
		awaitTerminationIfNecessary();
	}

	/**
	 * Wait for the executor to terminate, according to the value of the
	 * {@link #setAwaitTerminationSeconds "awaitTerminationSeconds"} property.
	 */
	private void awaitTerminationIfNecessary() {
		if (this.awaitTerminationSeconds > 0) {
			try {
				if (!this.executor.awaitTermination(this.awaitTerminationSeconds, TimeUnit.SECONDS)) {
					if (logger.isWarnEnabled()) {
						logger.warn("Timed out while waiting for executor" +
								(this.beanName != null ? " '" + this.beanName + "'" : "") + " to terminate");
					}
				}
			}
			catch (InterruptedException ex) {
				if (logger.isWarnEnabled()) {
					logger.warn("Interrupted while waiting for executor" +
							(this.beanName != null ? " '" + this.beanName + "'" : "") + " to terminate");
				}
				Thread.currentThread().interrupt();
			}
		}
	}

posted @ 2018-04-12 14:56  冰凌花花~  阅读(254)  评论(0编辑  收藏  举报