......
......
//LockSupport.part()中检测到这个中断标志,会抛出InterruptedException,并清除线程的中断标志
//由于阻塞库函数,如:Object.wait,Thread.sleep除了抛出异常外,还会清除线程中断状态,因此可能在这里要保留线程的中断状态
......
在学校的论坛Java版发现很多问关于这样的问题,比如这几个方法有什么区别,想看t.interrupt()方法后线程的中断状态;如何终止一个线程
其实之前已经大部分提及到。现总结一下,然后加上例子,毕竟例子容易理解
http://www.blogjava.net/fhtdy2004/archive/2009/06/08/280728.html中有关interrupt()的解释已经很清楚了
interruptpublic void interrupt()
中断线程。
如果当前线程没有中断它自己(这在任何情况下都是允许的),则该线程的 checkAccess 方法就会被调用,这可能抛出 SecurityException。
如果线程在调用 Object 类的 wait()、wait(long) 或 wait(long, int) 方法,或者该类的 join()、join(long)、join(long, int)、sleep(long) 或 sleep(long, int) 方法过程中受阻,则其中断状态将被清除,它还将收到一个 InterruptedException。
如果该线程在可中断的通道上的 I/O 操作中受阻,则该通道将被关闭,该线程的中断状态将被设置并且该线程将收到一个 ClosedByInterruptException。
如果该线程在一个 Selector 中受阻,则该线程的中断状态将被设置,它将立即从选择操作返回,并可能带有一个非零值,就好像调用了选择器的 wakeup 方法一样。
如果以前的条件都没有保存,则该线程的中断状态将被设置。
抛出:
SecurityException - 如果当前线程无法修改该线程
--------------------------------------------------------------------------------
interruptedpublic static boolean interrupted()
测试当前线程是否已经中断。线程的中断状态 由该方法清除。换句话说,如果连续两次调用该方法,则第二次调用将返回 false(在第一次调用已清除了其中断状态之后,且第二次调用检验完中断状态前,当前线程再次中断的情况除外)。
返回:
如果当前线程已经中断,则返回 true;否则返回 false。
另请参见:
isInterrupted()
--------------------------------------------------------------------------------
isInterruptedpublic boolean isInterrupted()
测试线程是否已经中断。线程的中断状态 不受该方法的影响。
返回:
如果该线程已经中断,则返回 true;否则返回 false。
另请参见:
interrupted()
t.interrupt()不会中断正在执行的线程,只是将线程的标志位设置成true。但是如果线程在调用sleep(),join(),wait()方法时线程被中断,则这些方法会抛出InterruptedException,在catch块中捕获到这个异常时,线程的中断标志位已经被设置成false了,因此在此catch块中调用t.isInterrupted(),Thread.interrupted()始终都为false,
而t.isInterrupted与Thread.interrupted()的区别是API中已经说明很明显了,Thread.interrupted()假如当前的中断标志为true,则调完后会将中断标志位设置成false
- package threadtest;
-
- import java.util.Timer;
- import java.util.TimerTask;
-
- class CanStop extends Thread {
-
- private int counter = 0;
-
- public void run() {
- boolean done = false;
- try{
- Thread.sleep(100);
- }catch(InterruptedException ie){
- ie.printStackTrace();
-
- }
- while (counter < 100000 &&!done) {
- System.out.println(counter++);
-
-
- System.out.println("in thread stoppable.isInterrupted() "+isInterrupted());
-
-
-
-
- if(Thread.interrupted()==true){
- try{
-
- System.out.println("in thread after Thread.interrupted() "+isInterrupted());
- sleep(10000);
- }catch(InterruptedException ie){
- ie.printStackTrace();
-
- }
- }
- }
- }
-
- }
-
- public class CheckInterrupt {
- public static void main(String[] args) {
- final CanStop stoppable = new CanStop();
- stoppable.start();
- new Timer(true).schedule(new TimerTask() {
- public void run() {
- System.out.println("Requesting Interrupt");
- stoppable.interrupt();
- System.out.println("in timer stoppable.isInterrupted() "+stoppable.isInterrupted());
- }
- }, 500);
- }
- }
-
-
- 2,关于interrupte()打断sleep()
- package threadtest;
-
-
-
- class Sleeper extends Thread {
- private int duration;
-
- public Sleeper(String name, int sleepTime) {
- super(name);
- duration = sleepTime;
- start();
- }
-
- public void run() {
- try {
- sleep(duration);
- } catch (InterruptedException e) {
-
-
- System.out.println(getName() + " in catch Thread.interrupted(). "
- + "Thread.interrupted(): " + Thread.interrupted());
- return;
- }
- System.out.println(getName() + " has awakened");
- }
- }
-
- class Joiner extends Thread {
- private Sleeper sleeper;
-
- public Joiner(String name, Sleeper sleeper) {
- super(name);
- this.sleeper = sleeper;
- start();
- }
-
- public void run() {
- try {
- sleeper.join();
- } catch (InterruptedException e) {
-
-
-
- throw new RuntimeException(e);
- }
- System.out.println(getName() + " join completed");
- }
- }
-
- public class Joining {
-
- public static void main(String[] args) {
- Sleeper sleepy = new Sleeper("Sleepy", 1500),
- grumpy = new Sleeper("Grumpy", 1500);
- Joiner dopey = new Joiner("Dopey", sleepy),
- doc = new Joiner("Doc",grumpy);
- grumpy.interrupt();
-
-
- }
- }
-
- Sleeper是一个会睡上一段时间的Thread,至于睡多长时间,这要由构造函数的参数决定。Sleeper的run( )的sleep( )可以因时限到期而返回,也可以被interrupt( )打断。catch语句在报告中断的同时,会一并报告isInterrupted( )。当有别的线程调用了本线程的interrupt( )时,会设置一个标记以表示这个这个线程被打断了。当本线程捕获这个异常的时候,会清除这个标志。所以catch语句会永远报告说isInterrupted( )是false。这个标记是用来应付其它情况的,或许在没出异常的情况下,线程要用它来检查自己是不是被中断了。
- Joiner是另一个线程,它调用了Sleeper的join( ),所以它要等Sleeper醒过来。main( )创建了两个Sleeper分派给两个Joiner。你会发现,不论Sleeper是被打断还是正常结束,Joiner都会随Sleeper一道结束。
-
-
-
-
-
- 2,如何终止一个线程:
- package test.thread.one;
-
- import java.util.Timer;
- import java.util.TimerTask;
-
- class CanStop extends Thread {
-
- private volatile boolean stop = false;
-
- private int counter = 0;
-
- public void run() {
- while (!stop && counter < 100000) {
- System.out.println(counter++);
- }
- if (stop)
- System.out.println("Detected stop");
- }
-
- public void requestStop() {
- stop = true;
- }
- }
-
- public class Stopping {
- public static void main(String[] args) {
- final CanStop stoppable = new CanStop();
- stoppable.start();
- new Timer(true).schedule(new TimerTask() {
- public void run() {
- System.out.println("Requesting stop");
- stoppable.requestStop();
- }
- }, 500);
- }
- }
stop必须是volatile的,这样才能确保run( )方法能看到它(否则它会使用本地的缓存值)。这个线程的"任务"是打印10,000个数字,所以当counter >= 10000或有人要它停下来的时候,它就结束了。注意requestStop( )不是synchronized,因为stop既是boolean(改成true是一个原子操作)又是volatile的。
或者
- package test.thread.three;
-
- import java.util.Timer;
- import java.util.TimerTask;
-
- class CanStop extends Thread {
-
- private boolean stop = false;
-
- private int counter = 0;
-
- public void run() {
- boolean done = false;
- try{
- Thread.sleep(100);
- }catch(InterruptedException ie){
- ie.printStackTrace();
-
- }
- while (!getStopRequest() && counter < 100000 &&!done) {
- System.out.println(counter++);
- }
- if (getStopRequest())
- System.out.println("Detected stop");
- }
-
-
- public synchronized boolean getStopRequest(){
- return stop;
- }
-
- public synchronized void requestStop() {
- stop = true;
- }
- }
-
- public class Stopping {
- public static void main(String[] args) {
- final CanStop stoppable = new CanStop();
- stoppable.start();
- new Timer(true).schedule(new TimerTask() {
- public void run() {
- System.out.println("Requesting stop");
- stoppable.requestStop();
- }
- }, 500);
- }
- }
-
- 打断受阻的线程
- 有时线程受阻之后就不能再做轮询了,比如在等输入,这时你就不能像前面那样去查询旗标了。碰到这种情况,你可以用Thread.interrupt( )方法打断受阻的线程:
-
-
-
- import java.util.*;
- class Blocked extends Thread {
- public Blocked() {
- System.out.println("Starting Blocked");
- start();
- }
- public void run() {
- try {
- synchronized(this) {
- wait();
- }
- } catch(InterruptedException e) {
- System.out.println("Interrupted");
- }
- System.out.println("Exiting run()");
- }
- }
- public class Interrupt {
- static Blocked blocked = new Blocked();
- public static void main(String[] args) {
- new Timer(true).schedule(new TimerTask() {
- public void run() {
- System.out.println("Preparing to interrupt");
- blocked.interrupt();
- blocked = null;
- }
- }, 2000);
- }
- }
3.避免过多的同步,永远不要在循环外面调用wait
为了避免死锁的危险,在一个被同步的的方法或者代码快中,永远不要放弃对客户的限制。
换句话说,在一个被同步的区域内部,不要调用一个可被改写的公有或受保护的方法(这样的方法往往是一个抽象方法,但偶尔他们也会有一个默认的实现,)从包含该同步区域的类的角度来看,这样的方法是一个外来者alien。这个类不知道该类会做什么事情,也控制不力它。客户可以为这个外来方法提供一个实现,并且在该方法中创建了一个线程,再回调到这个类中。然后,新建的线程试图获取原线程所拥有的那把锁,这样会导致新建的线程被阻塞。如果创建该线程的方法在等待这个线程完成这个任务,则死锁就形成了。
Object.wait方法的作用是使一个线程等待某个条件。它一定是在一个同步区域中被调用,而且该同步区域锁住了被调用的对象。下面是wait方法的标准模式:
- synchronized(obj){
- while()
- obj.wait();
- ...
- }
总是使用wait循环模式来调用wait方法。而不是if来调用。永远不要在循环的外面调用wait。循环被用于等待的前后测试条件
4.保持可运行线程数量尽可能的少的主要技术是,让每个线程做少量的工作,然后使用Object.wait等待某个条件发生,或者使用Thread.sleep()睡眠一段时间,线程不应该忙-等busy-wait,即反复的检查一个数据结构,以等待某些事件发生。除了使程序易受调度器的变化的影响外,忙等这种做法还会增加处理器的负担
busy-wait
- package effective.java;
-
- import java.util.LinkedList;
- import java.util.List;
-
- public abstract class WorkQueueBusyWait {
-
- private final List queue = new LinkedList();
-
- private boolean stopped = false;
-
- protected WorkQueueBusyWait(){
- new WorkThread().start();
- }
-
- public final void enqueue(Object workItem){
- synchronized(queue){
- queue.add(workItem);
- }
- }
-
- public final void stop(){
- synchronized(queue){
- stopped = true;
- }
- }
-
- protected abstract void processItem(Object workitem) throws InterruptedException;
-
- private class WorkThread extends Thread{
- public void run(){
- final Object QUEUE_IS_EMPTY = new Object();
- while(true){
- Object workItem = QUEUE_IS_EMPTY;
- synchronized(queue){
- if(stopped)
- return;
- if(!queue.isEmpty())
- workItem = queue.remove(0);
- }
- if(workItem != QUEUE_IS_EMPTY){
- try{
- processItem(workItem);
- }catch(InterruptedException ie){
- ie.printStackTrace();
- return;
- }
- }
- }
- }
- }
- }
-
- class PingPongQueue extends WorkQueue{
- volatile int count=0;
- @Override
- protected void processItem(final Object workItem) throws InterruptedException {
- count++;
- WorkQueue recipient = (WorkQueue)workItem;
- recipient.enqueue(this);
- }
-
- }
-
- package effective.java;
-
- public class WaitQueuePerf {
-
-
-
-
- public static void main(String[] args) {
-
- PingPongQueue q1 = new PingPongQueue();
- PingPongQueue q2 = new PingPongQueue();
- q1.enqueue(q2);
-
- try{
- Thread.sleep(1000);
- }catch(InterruptedException ie){
- ie.printStackTrace();
- }
-
- int count = q1.count;
- try{
- Thread.sleep(1000);
- }catch(InterruptedException ie){
- ie.printStackTrace();
- }
- System.out.println(q1.count-count);
- q1.stop();
- q2.stop();
-
- }
-
- }