Thread类的interrupt,interrupted,isInterrupted方法的理解

2024-01-07 09:48

本文主要是介绍Thread类的interrupt,interrupted,isInterrupted方法的理解,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

http://www.blogjava.net/fhtdy2004/archive/2009/08/22/292181.html


http://www.blogjava.net/fhtdy2004/category/39225.html此博客值得好好学习!!!


t.interrupt(),t.isInterrupted(),Thread.interrupted()
在学校的论坛Java版发现很多问关于这样的问题,比如这几个方法有什么区别,想看t.interrupt()方法后线程的中断状态;如何终止一个线程
其实之前已经大部分提及到。现总结一下,然后加上例子,毕竟例子容易理解
http://www.blogjava.net/fhtdy2004/archive/2009/06/08/280728.html中有关interrupt()的解释已经很清楚了

interrupt

public 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 - 如果当前线程无法修改该线程

interrupted

public static boolean interrupted()
测试当前线程是否已经中断。线程的 中断状态 由该方法清除。换句话说,如果连续两次调用该方法,则第二次调用将返回 false(在第一次调用已清除了其中断状态之后,且第二次调用检验完中断状态前,当前线程再次中断的情况除外)。

 


返回:
如果当前线程已经中断,则返回 true;否则返回 false
另请参见:
isInterrupted()

isInterrupted

public 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);//设置成100比主线程中的500要小
        }
catch(InterruptedException ie){
            ie.printStackTrace();
            
//return;假如要使用interrupt来终止线程则在捕获的InterruptedException中return
        }

        
while (counter < 100000 &&!done) {
            System.out.println(counter
++);
            
//在主线程中调用stoppable.interrupt()之前为false,假如之后没有调用Thread.interrupted()则一直为true,
            
//否则为第一次为true,调用Thread.interrupted之后为false
            System.out.println("in thread stoppable.isInterrupted() "+isInterrupted());
            
            
//System.out.println("stoppable.isInterrupted() "+Thread.interrupted());在主线程中调用stoppable.interrupt()之前为false,之后只有第一个会显示为true,之后全为false
            
            
//调用Thread.interrupted()一次会清除线程的中断标志位,因此以后都为false
            if(Thread.interrupted()==true){
                
try{
                    
//Thread.interrupted()会清除中断标志位,显然这里面只会调用一次
                    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();
//不会中断正在执行的线程,原因是因为interrupt()方法只设置中断状态标志位为true
                System.out.println("in timer stoppable.isInterrupted() "+stoppable.isInterrupted());
            }

        }
500); // run() after 500 milliseconds
    }

}



2,关于interrupte()打断sleep()
package  threadtest;

// Understanding join().

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() + " was interrupted. " +
            
// "isInterrupted(): " + isInterrupted());
            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) {
            
//run方法不能Throw CheckedException,要抛只能抛出RuntimeException,也不会被主线程捕获
            //要使主线程能够捕获这个RuntimeException请参见另外一篇文章
            //地址:http://www.blogjava.net/fhtdy2004/archive/2009/08/07/290210.html

            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();
        //doc.interrupt();

    }

}

Sleeper是一个会睡上一段时间的Thread,至于睡多长时间,这要由构造函数的参数决定。Sleeperrun( )sleep( )可以因时限到期而返回,也可以被interrupt( )打断。catch语句在报告中断的同时,会一并报告isInterrupted( )当有别的线程调用了本线程的interrupt( )时,会设置一个标记以表示这个这个线程被打断了。当本线程捕获这个异常的时候,会清除这个标志。所以catch语句会永远报告说isInterrupted( )是false。这个标记是用来应付其它情况的,或许在没出异常的情况下,线程要用它来检查自己是不是被中断了。
Joiner是另一个线程,它调用了Sleeperjoin( ),所以它要等Sleeper醒过来。main( )创建了两个Sleeper分派给两个Joiner。你会发现,不论Sleeper是被打断还是正常结束,Joiner都会随Sleeper一道结束。





2,如何终止一个线程:
package  test.thread.one;

import  java.util.Timer;
import  java.util.TimerTask;

class  CanStop  extends  Thread  {
    
// Must be volatile:
    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); // run() after 500 milliseconds
    }

}

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();
            
//return;假如要使用interrupt来终止线程则在捕获的InterruptedException中return
        }

        
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); // run() after 500 milliseconds
    }

}


打断受阻的线程
有时线程受阻之后就不能再做轮询了,比如在等输入,这时你就不能像前面那样去查询旗标了。碰到这种情况,你可以用Thread.interrupt( )方法打断受阻的线程:

// : c13:Interrupt.java
//  Using interrupt() to break out of a blocked thread.
import  java.util. * ;
class  Blocked  extends  Thread  {
  
public Blocked() {
    System.out.println(
"Starting Blocked");
    start();
  }

  
public void run() {
    
try {
      
synchronized(this{
        wait(); 
// Blocks
      }

    }
 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// to release it
      }

    }
2000); // run() after 2000 milliseconds
  }

}
  // /


3.避免过多的同步,永远不要在循环外面调用wait

为了避免死锁的危险,在一个被同步的的方法或者代码快中,永远不要放弃对客户的限制。
换句话说,在一个被同步的区域内部,不要调用一个可被改写的公有或受保护的方法(这样的方法往往是一个抽象方法,但偶尔他们也会有一个默认的实现,)从包含该同步区域的类的角度来看,这样的方法是一个外来者alien。这个类不知道该类会做什么事情,也控制不力它。客户可以为这个外来方法提供一个实现,并且在该方法中创建了一个线程,再回调到这个类中。然后,新建的线程试图获取原线程所拥有的那把锁,这样会导致新建的线程被阻塞。如果创建该线程的方法在等待这个线程完成这个任务,则死锁就形成了。


Object.wait方法的作用是使一个线程等待某个条件。它一定是在一个同步区域中被调用,而且该同步区域锁住了被调用的对象。下面是wait方法的标准模式:
synchronized(obj){
      while(<condition does not hold>)
            obj.wait();
      ...//perform action appropriate to condition
}
总是使用wait循环模式来调用wait方法。而不是if来调用。永远不要在循环的外面调用wait。循环被用于等待的前后测试条件

package  effective.java;

import  java.io.BufferedInputStream;
import  java.util.LinkedList;
import  java.util.List;

public   abstract   class  WorkQueue  {
    
    
private final List queue = new LinkedList();
    
    
private boolean stopped = false;
    
    StringBuffer sb;
    BufferedInputStream bis;
    
    
protected WorkQueue(){
        
new WorkerThread2().start();
    }

    
    
public final void enqueue(Object workItem){
        
synchronized(queue){
            queue.add(workItem);
            queue.notify();
        }

    }

    
    
public final void stop(){
        
synchronized(queue){
            stopped 
= true;
            queue.notify();
        }

    }

    
    
protected abstract void processItem(Object workItem)throws InterruptedException;
    
    
//Broken - invokes alien method from synchronized block
    private class WorkerThread extends Thread{
        
public void run(){
            
while(true){
                
synchronized(WorkQueue.this.queue){
                    
try{
                        
while(queue.isEmpty() && !stopped){
                            queue.wait();
                        }

                    }
catch(InterruptedException ie){
                        ie.printStackTrace();
                        
return;
                    }

                    
                    
if(stopped)
                        
return;
                    Object workItem 
= queue.remove(0);
                    
try{
                        processItem(workItem);
//lock held
                    }
catch(InterruptedException ie){
                        System.out.println(
"ddd"+ie);
                        
return;
                    }

                }

            }

        }

    }

    
    
    
//Alien method outside synchronized block -"open call"
    private class WorkerThread2 extends Thread{
        
public void run(){
            
while(true){
                Object workItem 
= null;
                
synchronized(WorkQueue.this.queue){
                    
try{
                        
while(queue.isEmpty() && !stopped){
                            queue.wait();
                        }

                    }
catch(InterruptedException ie){
                        
return;
                    }

                    
                    
if(stopped)
                        
return;
                    workItem 
= queue.remove(0);    
                }

                
                
try{
                    processItem(workItem);
//No lock held
                }
catch(InterruptedException ie){
                    
return;
                }

            }

        }

    }

}


package  effective.java;

public   class  DisplayQueue  extends  WorkQueue  {

    @Override
    
protected void processItem(Object workItem) throws InterruptedException {
        System.out.println(workItem);
        System.out.println(
"模拟此线程做耗时工作");
        Thread.sleep(
1000);
    }

    
    
public static void main(String[] args){
        WorkQueue wq 
= new DisplayQueue();
        
for(int i=0;i<10;i++){
            String s 
= new String("object_"+i);
            System.out.println(
"main thread add " + s+" to queue");
            wq.enqueue(s);
            
try{
                Thread.sleep(
500);
            }
catch(InterruptedException ie){
                ie.printStackTrace();
            }

        }

        
//wq.stop();
    }


}




class  DeadLockQueue  extends  WorkQueue {

    @Override
    
protected void processItem(final Object workItem) throws InterruptedException {
        
        Thread child 
= new Thread(){
            
public void run(){
                
//DeadLockQueue.this.enqueue(workItem);
                System.out.println("在将对象入队列 "+workItem);
                enqueue(workItem);
            }

        }
;
        child.start();
        child.join();
//dead lock
        
    }

    
    
}



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  {

    
/**
     * 
@param args
     
*/

    
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();

    }


}



这篇关于Thread类的interrupt,interrupted,isInterrupted方法的理解的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/579517

相关文章

Nginx安全防护的多种方法

《Nginx安全防护的多种方法》在生产环境中,需要隐藏Nginx的版本号,以避免泄漏Nginx的版本,使攻击者不能针对特定版本进行攻击,下面就来介绍一下Nginx安全防护的方法,感兴趣的可以了解一下... 目录核心安全配置1.编译安装 Nginx2.隐藏版本号3.限制危险请求方法4.请求限制(CC攻击防御)

python生成随机唯一id的几种实现方法

《python生成随机唯一id的几种实现方法》在Python中生成随机唯一ID有多种方法,根据不同的需求场景可以选择最适合的方案,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来一起学习学习... 目录方法 1:使用 UUID 模块(推荐)方法 2:使用 Secrets 模块(安全敏感场景)方法

MyBatis-Plus通用中等、大量数据分批查询和处理方法

《MyBatis-Plus通用中等、大量数据分批查询和处理方法》文章介绍MyBatis-Plus分页查询处理,通过函数式接口与Lambda表达式实现通用逻辑,方法抽象但功能强大,建议扩展分批处理及流式... 目录函数式接口获取分页数据接口数据处理接口通用逻辑工具类使用方法简单查询自定义查询方法总结函数式接口

MySQL深分页进行性能优化的常见方法

《MySQL深分页进行性能优化的常见方法》在Web应用中,分页查询是数据库操作中的常见需求,然而,在面对大型数据集时,深分页(deeppagination)却成为了性能优化的一个挑战,在本文中,我们将... 目录引言:深分页,真的只是“翻页慢”那么简单吗?一、背景介绍二、深分页的性能问题三、业务场景分析四、

JAVA中安装多个JDK的方法

《JAVA中安装多个JDK的方法》文章介绍了在Windows系统上安装多个JDK版本的方法,包括下载、安装路径修改、环境变量配置(JAVA_HOME和Path),并说明如何通过调整JAVA_HOME在... 首先去oracle官网下载好两个版本不同的jdk(需要登录Oracle账号,没有可以免费注册)下载完

深入理解Go语言中二维切片的使用

《深入理解Go语言中二维切片的使用》本文深入讲解了Go语言中二维切片的概念与应用,用于表示矩阵、表格等二维数据结构,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来一起学习学习吧... 目录引言二维切片的基本概念定义创建二维切片二维切片的操作访问元素修改元素遍历二维切片二维切片的动态调整追加行动态

Java中读取YAML文件配置信息常见问题及解决方法

《Java中读取YAML文件配置信息常见问题及解决方法》:本文主要介绍Java中读取YAML文件配置信息常见问题及解决方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要... 目录1 使用Spring Boot的@ConfigurationProperties2. 使用@Valu

Java 方法重载Overload常见误区及注意事项

《Java方法重载Overload常见误区及注意事项》Java方法重载允许同一类中同名方法通过参数类型、数量、顺序差异实现功能扩展,提升代码灵活性,核心条件为参数列表不同,不涉及返回类型、访问修饰符... 目录Java 方法重载(Overload)详解一、方法重载的核心条件二、构成方法重载的具体情况三、不构

SQL中如何添加数据(常见方法及示例)

《SQL中如何添加数据(常见方法及示例)》SQL全称为StructuredQueryLanguage,是一种用于管理关系数据库的标准编程语言,下面给大家介绍SQL中如何添加数据,感兴趣的朋友一起看看吧... 目录在mysql中,有多种方法可以添加数据。以下是一些常见的方法及其示例。1. 使用INSERT I

Python中反转字符串的常见方法小结

《Python中反转字符串的常见方法小结》在Python中,字符串对象没有内置的反转方法,然而,在实际开发中,我们经常会遇到需要反转字符串的场景,比如处理回文字符串、文本加密等,因此,掌握如何在Pyt... 目录python中反转字符串的方法技术背景实现步骤1. 使用切片2. 使用 reversed() 函