Java Executor是一个功能丰富,接口设计很好的,基于生产者-消费者模式的通用线程池。这种线程池的设计思想也在很多地方被应用。
通常来说,一个线程池的实现包括四个部分:
- 执行任务的线程
- 用于封装任务的task对象
- 存储任务的数据结构
- 线程池本身
1 Thread
Thread 并不是concurrent包的一部分。Thread包含着name, priority等成员和对应的操作方法。
它是继承自runable的,也就是说线程的入口函数是run。它的继承体系和重要操作函数如下图:
它实现了一系列包括sleep, yield等静态方法。以及获取当前线程的静态方法currentThread()。这些都是native方法。
中断机制:
- 通过调用interrupt来触发一个中断
- isInterrupted() 用来查询线程的中断状态
- interrupted() 用来查询并清除线程的中断状态
/**
* Interrupts this thread.
*
* <p> Unless the current thread is interrupting itself, which is
* always permitted, the {@link #checkAccess() checkAccess} method
* of this thread is invoked, which may cause a {@link
* SecurityException} to be thrown.
*
* <p> If this thread is blocked in an invocation of the {@link
* Object#wait() wait()}, {@link Object#wait(long) wait(long)}, or {@link
* Object#wait(long, int) wait(long, int)} methods of the {@link Object}
* class, or of the {@link #join()}, {@link #join(long)}, {@link
* #join(long, int)}, {@link #sleep(long)}, or {@link #sleep(long, int)},
* methods of this class, then its interrupt status will be cleared and it
* will receive an {@link InterruptedException}.
*
* <p> If this thread is blocked in an I/O operation upon an {@link
* java.nio.channels.InterruptibleChannel </code>interruptible
* channel<code>} then the channel will be closed, the thread's interrupt
* status will be set, and the thread will receive a {@link
* java.nio.channels.ClosedByInterruptException}.
*
* <p> If this thread is blocked in a {@link java.nio.channels.Selector}
* then the thread's interrupt status will be set and it will return
* immediately from the selection operation, possibly with a non-zero
* value, just as if the selector's {@link
* java.nio.channels.Selector#wakeup wakeup} method were invoked.
*
* <p> If none of the previous conditions hold then this thread's interrupt
* status will be set. </p>
*
* <p> Interrupting a thread that is not alive need not have any effect.
*
* @throws SecurityException
* if the current thread cannot modify this thread
*
* @revised 6.0
* @spec JSR-51
*/
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();
}
在默认的情况下,blocker (Interruptible 成员变量)的值为null, 这时调用interrupt,仅仅是调用interrupt0设置一个标志位。
而如果blocker的值不为null,则会调用其interrupt方法实现真正的中断。
(关于blocker值何时被设置,在后面会看到一个使用场景。)
当线程处于可中断的阻塞状态时,比如说阻塞在sleep, wait, join,select等操作时,调用interrupt方法会让线程从阻塞状态退出,并抛出InterruptedException。
值得注意的一点是:interrupt让我们从阻塞的方法中退出,但线程的中断状态却并不会被设置!
try {
Thread.sleep(10);
}
catch (InterruptedException e) {
System.out.println("IsInterrupted: " + Thread.currentThread().isInterrupted());
}
如上述示例代码,此时你得到的输出是: IsInterrupted : false 。这是一个有点令人意外的地方。
上述代码并 不是一个好的示例,因为interrupt被我们“吃”掉了!除非你明确的知道这是你想要的。否则的话请考虑在异常捕获中(catch段中)加上:
Thread.currentThread.interrupt();