当前位置:天才代写 > tutorial > JAVA 教程 > Java多线程:“基本篇”09之interrupt()和线程终止方法

Java多线程:“基本篇”09之interrupt()和线程终止方法

2017-11-02 08:00 星期四 所属: JAVA 教程 浏览:48

副标题#e#

1. interrupt()说明

在先容终止线程的方法之前,有须要先对interrupt()举办相识。

关于interrupt(),java的djk文档描写如下:

http://docs.oracle.com/javase/7/docs/api/

Interrupts this thread.

Unless the current thread is interrupting itself, which is always permitted, the checkAccess method of this thread is invoked, which may cause a SecurityException to be thrown.

If this thread is blocked in an invocation of the wait(), wait(long), or wait(long, int) methods of the Object class, or of the join(), join(long), join(long, int), sleep(long), or sleep(long, int), methods of this class, then its interrupt status will be cleared and it will receive an InterruptedException.

If this thread is blocked in an I/O operation upon an interruptible channel then the channel will be closed, the thread’s interrupt status will be set, and the thread will receive a ClosedByInterruptException.

If this thread is blocked in a 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 wakeup method were invoked.

If none of the previous conditions hold then this thread’s interrupt status will be set.

Interrupting a thread that is not alive need not have any effect.

大抵意思是:

interrupt()的浸染是间断本线程。

本线程间断本身是被答允的;其它线程挪用本线程的interrupt()要领时,会通过checkAccess()查抄 权限。这有大概抛出SecurityException异常。

假如本线程是处于阻塞状态:挪用线程的wait(), wait(long)或wait(long, int)会让它进入期待(阻 塞)状态,可能挪用线程的join(), join(long), join(long, int), sleep(long), sleep(long, int)也 会让它进入阻塞状态。若线程在阻塞状态时,挪用了它的interrupt()要领,那么它的“间断状态 ”会被排除而且会收到一个InterruptedException异常。譬喻,线程通过wait()进入阻塞状态,此 时通过interrupt()间断该线程;挪用interrupt()会当即将线程的间断标志设为“true”,但 是由于线程处于阻塞状态,所以该“间断标志”会当即被排除为“false”,同时 ,会发生一个InterruptedException的异常。

假如线程被阻塞在一个Selector选择器中,那么通过interrupt()间断它时;线程的间断标志会被配置 为true,而且它会当即从选择操纵中返回。

假如不属于前面所说的环境,那么通过interrupt()间断线程时,它的间断标志会被配置为 “true”。

间断一个“已终止的线程”不会发生任何操纵。

2. 终止线程的方法

Thread中的stop()和suspend()要领,由于固有的不安详性,已经发起不再利用!

下面,我先别离接头线程在“阻塞状态”和“运行状态”的终止方法,然后再 总结出一个通用的方法。

2.1 终止处于“阻塞状态”的线程

凡是,我们通过“间断”方法终止处于“阻塞状态”的线程。

当线程由于被挪用了sleep(), wait(), join()等要领而进入阻塞状态;若此时挪用线程的interrupt ()将线程的间断标志设为true。由于处于阻塞状态,间断标志会被排除,同时发生一个 InterruptedException异常。将InterruptedException放在适当的为止就能终止线程,形式如下:

@Override
public void run() {
    try {
        while (true) {
            // 执行任务...
        }
    } catch (InterruptedException ie) {  
        // 由于发生InterruptedException异常,退出while(true)轮回,线程终止!
    }
}

说明:在while(true)中不绝的执行任务,当线程处于阻塞状态时,挪用线程的interrupt()发生 InterruptedException间断。间断的捕捉在while(true)之外,这样就退出了while(true)轮回!

留意:对InterruptedException的捕捉务一般放在while(true)轮回体的外面,这样,在发生异常时就 退出了while(true)轮回。不然,InterruptedException在while(true)轮回体之内,就需要特另外添加退 出处理惩罚。形式如下:

@Override
public void run() {
    while (true) {
        try {
            // 执行任务...
        } catch (InterruptedException ie) {  
            // InterruptedException在while(true)轮回体内。
            // 当线程发生了InterruptedException异常时,while(true)仍能继承运行!需要手动退出
            break;
        }
    }
}

说明:上面的InterruptedException异常的捕捉在whle(true)之内。当发生InterruptedException异 常时,被catch处理惩罚之外,仍然在while(true)轮回体内;要退出while(true)轮回体,需要特另外执行退 出while(true)的操纵。


#p#副标题#e#

2.2 终止处于“运行状态”的线程

凡是,我们通过“标志”方法终止处于“运行状态”的线程。个中,包罗 “间断标志”和“特别添加标志”。

(01) 通过“间断标志”终止线程。

形式如下:

@Override
public void run() {
    while (!isInterrupted()) {
        // 执行任务...
    }
}

#p#分页标题#e#

说明:isInterrupted()是判定线程的间断标志是不是为true。当线程处于运行状态,而且我们需要终 止它时;可以挪用线程的interrupt()要领,利用线程的间断标志为true,即isInterrupted()会返回true 。此时,就会退出while轮回。

留意:interrupt()并不会终止处于“运行状态”的线程!它会将线程的间断标志设为true 。

(02) 通过“特别添加标志”。

形式如下:

private volatile boolean flag= true;
protected void stopTask() {
    flag = false;
}
    
@Override
public void run() {
    while (flag) {
        // 执行任务...
    }
}

说明:线程中有一个flag标志,它的默认值是true;而且我们提供stopTask()来配置flag标志。当我 们需要终止该线程时,挪用该线程的stopTask()要领就可以让线程退出while轮回。

留意:将flag界说为volatile范例,是为了担保flag的可见性。即其它线程通过stopTask()修改了 flag之后,本线程能看到修改后的flag的值。

综合线程处于“阻塞状态”和“运行状态”的终止方法,较量通用的终止线程 的形式如下:

@Override
public void run() {
    try {
        // 1. isInterrupted()担保,只要间断标志为true就终止线程。
        while (!isInterrupted()) {
            // 执行任务...
        }
    } catch (InterruptedException ie) {  
        // 2. InterruptedException异常担保,当InterruptedException异常发生时,线程被终止。
    }
}

3. 终止线程的示例

interrupt()经常被用来终止“阻塞状态”线程。参考下面示例:

// Demo1.java的源码
class MyThread extends Thread {
        
    public MyThread(String name) {
        super(name);
    }
    
    @Override
    public void run() {
        try {  
            int i=0;
            while (!isInterrupted()) {
                Thread.sleep(100); // 休眠100ms
                i++;
                System.out.println(Thread.currentThread().getName()+" 

("+this.getState()+") loop " + i);  
            }
        } catch (InterruptedException e) {  
            System.out.println(Thread.currentThread().getName() +" 

("+this.getState()+") catch InterruptedException.");  
        }
    }
}
    
public class Demo1 {
    
    public static void main(String[] args) {  
        try {  
            Thread t1 = new MyThread("t1");  // 新建“线程t1”
            System.out.println(t1.getName() +" ("+t1.getState()+") is new.");  
    
            t1.start();                      // 启动“线程t1”
            System.out.println(t1.getName() +" ("+t1.getState()+") is started.");  
    
            // 主线程休眠300ms,然后主线程给t1发“间断”指令。
            Thread.sleep(300);
            t1.interrupt();
            System.out.println(t1.getName() +" ("+t1.getState()+") is interrupted.");
    
            // 主线程休眠300ms,然后查察t1的状态。
            Thread.sleep(300);
            System.out.println(t1.getName() +" ("+t1.getState()+") is interrupted now.");
        } catch (InterruptedException e) {  
            e.printStackTrace();
        }
    } 
}

#p#副标题#e#

运行功效:

t1 (NEW) is new.
t1 (RUNNABLE) is started.
t1 (RUNNABLE) loop 1
t1 (RUNNABLE) loop 2
t1 (TIMED_WAITING) is interrupted.
t1 (RUNNABLE) catch InterruptedException.
t1 (TERMINATED) is interrupted now.

功效说明:

(01) 主线程main中通过new MyThread("t1")建设线程t1,之后通过t1.start()启动线程t1 。

(02) t1启动之后,会不绝的查抄它的间断标志,假如间断标志为“false”;则休眠100ms 。

(03) t1休眠之后,会切换到主线程main;主线程再次运行时,会执行t1.interrupt()间断线程t1。t1 收到间断指令之后,会将t1的间断标志配置“false”,并且会抛出InterruptedException异 常。在t1的run()要领中,是在轮回体while之外捕捉的异常;因此轮回被终止。

我们对上面的功效举办小小的修改,将run()要领中捕捉InterruptedException异常的代码块移到 while轮回体内。

// Demo2.java的源码
class MyThread extends Thread {
        
    public MyThread(String name) {
        super(name);
    }
    
    @Override
    public void run() {
        int i=0;
        while (!isInterrupted()) {
            try {
                Thread.sleep(100); // 休眠100ms
            } catch (InterruptedException ie) {  
                System.out.println(Thread.currentThread().getName() +" ("+this.getState()+") catch InterruptedException.");  
            }
            i++;
            System.out.println(Thread.currentThread().getName()+" ("+this.getState()+") loop " + i);  

        }
    }
}
    
public class Demo2 {
    
    public static void main(String[] args) {  
        try {  
            Thread t1 = new MyThread("t1");  // 新建“线程t1”
            System.out.println(t1.getName() +" ("+t1.getState()+") is new.");  
    
            t1.start();                      // 启动“线程t1”
            System.out.println(t1.getName() +" ("+t1.getState()+") is started.");  
    
            // 主线程休眠300ms,然后主线程给t1发“间断”指令。
            Thread.sleep(300);
            t1.interrupt();
            System.out.println(t1.getName() +" ("+t1.getState()+") is interrupted.");
    
            // 主线程休眠300ms,然后查察t1的状态。
            Thread.sleep(300);
            System.out.println(t1.getName() +" ("+t1.getState()+") is interrupted now.");
        } catch (InterruptedException e) {  
            e.printStackTrace();
        }
    } 
}

查察本栏目
#p#分页标题#e#

运行功效:

t1 (NEW) is new.
t1 (RUNNABLE) is started.
t1 (RUNNABLE) loop 1
t1 (RUNNABLE) loop 2
t1 (TIMED_WAITING) is interrupted.
t1 (RUNNABLE) catch InterruptedException.
t1 (RUNNABLE) loop 3
t1 (RUNNABLE) loop 4
t1 (RUNNABLE) loop 5
t1 (TIMED_WAITING) is interrupted now.
t1 (RUNNABLE) loop 6
t1 (RUNNABLE) loop 7
t1 (RUNNABLE) loop 8
t1 (RUNNABLE) loop 9
...

#p#副标题#e#

功效说明:

措施进入了死轮回!

为什么会这样呢?这是因为,t1在“期待(阻塞)状态”时,被interrupt()间断;此时,会 排除间断标志[即isInterrupted()会返回false],并且会抛出InterruptedException异常[该异常在while 轮回体内被捕捉]。因此,t1理所虽然的会进入死轮回了。

办理该问题,需要我们在捕捉异常时,特另外举办退出while轮回的处理惩罚。譬喻,在MyThread的catch (InterruptedException)中添加break 或 return就能办理该问题。

下面是通过“特别添加标志”的方法终止“状态状态”的线程的示例:

// Demo3.java的源码
class MyThread extends Thread {
    
    private volatile boolean flag= true;
    public void stopTask() {
        flag = false;
    }
        
    public MyThread(String name) {
        super(name);
    }
    
    @Override
    public void run() {
        synchronized(this) {
            try {
                int i=0;
                while (flag) {
                    Thread.sleep(100); // 休眠100ms
                    i++;
                    System.out.println(Thread.currentThread().getName()+" 

("+this.getState()+") loop " + i);  
                }
            } catch (InterruptedException ie) {  
                System.out.println(Thread.currentThread().getName() +" ("+this.getState()+") catch InterruptedException.");  
            }
        }  
    }
}
    
public class Demo3 {
    
    public static void main(String[] args) {  
        try {  
            MyThread t1 = new MyThread("t1");  // 新建“线程t1”
            System.out.println(t1.getName() +" ("+t1.getState()+") is new.");  
    
            t1.start();                      // 启动“线程t1”
            System.out.println(t1.getName() +" ("+t1.getState()+") is started.");  
    
            // 主线程休眠300ms,然后主线程给t1发“间断”指令。
            Thread.sleep(300);
            t1.stopTask();
            System.out.println(t1.getName() +" ("+t1.getState()+") is interrupted.");
    
            // 主线程休眠300ms,然后查察t1的状态。
            Thread.sleep(300);
            System.out.println(t1.getName() +" ("+t1.getState()+") is interrupted now.");
        } catch (InterruptedException e) {  
            e.printStackTrace();
        }
    } 
}

运行功效:

t1 (NEW) is new.
t1 (RUNNABLE) is started.
t1 (RUNNABLE) loop 1
t1 (RUNNABLE) loop 2
t1 (TIMED_WAITING) is interrupted.
t1 (RUNNABLE) loop 3
t1 (TERMINATED) is interrupted now.

4. interrupted() 和 isInterrupted()的区别

最后谈谈 interrupted() 和 isInterrupted()。

interrupted() 和 isInterrupted()都可以或许用于检测工具的“间断标志”。

区别是,interrupted()除了返回间断标志之外,它还会排除间断标志(即将间断标志设为false);而 isInterrupted()仅仅返回间断标志。

 

    关键字:


天才代写-代写联系方式