黑马程序员技术交流社区

标题: 多线程中有关interrupt(),interrupted(),isInterrupted()方法的问题 [打印本页]

作者: 付玉光    时间: 2013-2-26 12:59
标题: 多线程中有关interrupt(),interrupted(),isInterrupted()方法的问题
本帖最后由 付玉光 于 2013-3-8 15:49 编辑

师哥师姐们,在帮小兄我一个大帮呀,自我感觉多线程这块真费解!


①wait(),notify(),notifyAll()都是操作线程的方法,为什么不定义在Thread类中,而定义在Object中呢?

②interrupt(),interrupted(),isInterrupted()这三个方法有什么区别和联系呀?仅仅一个静态的interrupted()方法就让我很挠头了!{:soso_e100:}



作者: 杜鹏飞    时间: 2013-2-26 14:12
本帖最后由 Pf_D 于 2013-2-26 14:13 编辑

多线程非一日之功,其所涉及的是一门学科,即Parallel Computatio。Jeffrey在其书《Windows Internal》中曾说他自上世纪九十年代开始写多线程程序,直到完成这本书时尚不能说自己写多线程程序可以确保无误。
每个函数的作用无法具体说明,文档中对此也是模模糊糊(楼主可以去看java.lang中的thread一节)

问题1
小生接触Java的时间较短,暂时无法替楼主解决。

问题2
void interrupt()
          Interrupts this thread.
static boolean interrupted()
          Tests whether the current thread has been interrupted
boolean isInterrupted()
          Tests whether this thread has been interrupted.
以上的this均指的是主调线程!

作者: 孙传磊    时间: 2013-2-27 12:27
1.  某线程必须获取欲调用实例的锁定,才能调用 wait 方法 notify方法,notifyAll方法。
   wait notify notifyAll都是java.lang的Object类的方法,不是Thread类固有的方法。
2.(1)interrupt:置线程的中断状态
  (2)isInterrupt:线程是否中断
  (3)interrupted:返回线程的上次的中断状态,并清除中断状态
       例如: 在 while(!Thread.currentThread().isInterrupted()) {  
                          当达到队列容量时,在这里会阻塞   
                  put的内部会调用LockSupport.park()这个是用来阻塞线程的方法   
                  当其他线程,调用此线程的interrupt()方法时,会设置一个中断标志   
                 LockSupport.part()中检测到这个中断标志,会抛出InterruptedException,并清除线程的中断标志
                 由于阻塞库函数,如:Object.wait,Thread.sleep除了抛出异常外,还会清除线程中断状态,因此可能在这里要保留线程的中断状态   
                 因此在异常段调用Thread.currentThread().isInterrupted()返回为false   
             另外,Thread.interrupted()在jdk库的源代码中比较常用,因为它既可以得到上一次线程的中断标志值,又可以同时清除线程的中断标志
                  若在得到一个异常的同时,线程的中断状态已经被清除了,需要保留线程的中断状态,则需要调用Thread.currentThread().interrupt()

作者: 付玉光    时间: 2013-3-7 16:28
本帖最后由 付玉光 于 2013-3-7 16:29 编辑

{:soso_e101:}有时,真郁闷,自己提的问题,自己回答,

关于第一个问题:

        这些方法都只能存在于同步代码块中,而使用这些方法时必须要标识所属的同步锁,
        而同步锁上监视器可以是任意对象,所以任意对象调用的方法一定要定义在object类中,
        才符合逻辑呀。


②第二个问题



//从该例中可证明,当前线程调用interrupt()方法并不能使,线程停止。

class MyClass1 extends Thread{
        public void run(){
                        for(int i=1;i<5;i++){
                                if(i>2)
                                        interrupt();
                                System.out.println(Thread.currentThread().getName()+" "+i);
                        }
        }

        public static void main(String[] args){
                        MyClass1 my=new MyClass1();
                        my.start();
        }
}

//该例证明:interrupted方法作用:是测试当前线程是否已经中断,线程的中断状态 由该方法清除。

class MyClass2 extends Thread{
        public void run(){
                try{
                                        for(int i=1;i<5;i++){
                                                System.out.print(i+" ");

                                                if(i>2)
                                                        interrupt();

                                                //该句作用:清除中断状态,使程序继续运行。
                                                interrupted();

                                                sleep(1000);
                                                        
                                        }
                }catch(InterruptedException e){
                        System.out.println("caught");
                }
        }

        public static void main(String[] args){
                        MyClass2 my=new MyClass2();
                        my.start();
        }
}

//isInterrupt方法的作用是:测试线程是否已经中断,如果已经中断,则返回 true;否则返回 false。

class MyClass3 extends Thread{

        public void run(){
                        int i=0;
                try{
                                        //如果中断,则退出循环。
                                        while(!isInterrupted()){
                                                ++i;
                                                System.out.println(Thread.currentThread().getName()+" "+i);
                                                if(i>4)
                                                        interrupt();
                                                sleep(1000);
                                                        
                                        }
                }catch(InterruptedException e){
                        System.out.println("结束");
                }
        }

        public static void main(String[] args){
                        MyClass3 my=new MyClass3();
                        my.start();
        }
}


interrupt方法:它是Thread类中的方法,该方法的作用是:把线程的运行状态改变为中断,

但当对象调用它时,并不用立即让线程停止运行。这点是很多人都不注意,

很多人都认为:线程的中断就是让线程停止.这其实是错误的观点,因为这只是改变了

线程的中断状态,线程并不会立即停止运行,当我们在一个线程对象上调用interrupt()方法,

真正有影响的是wait,join,sleep方法,当然也包括它们的重载方法。

你说的这三个方法都不会抛出InterruptedException,但受影响的wait,join,sleep方法

以即它们的重载形式将会抛出InterruptedException异常。

也就是说,如果一个线程被调用了interrupt()后,它的状态是已中断的.

这个状态对于正在执行wait,join,sleep方法的线程会受到影响,从而抛出中断异常。


为什么调用interrupt方法不会立即使线程停止运行呢?

那是因为多线程的产生目的是提高CPU的利用率(提高处理数据的效率),

但要提高效率(一个更重要)的前提也要保证处理数据的完整性,

给你举个例子,

synchronized void {
         x = 3;
         y = 4;
}
这个方法是同步的,多个线程访问时总能保证x,y被同时赋值,而如果一个线程正在执行到

x = 3;时,被调用了interrupt方法使线程停止了,即使是在同步块中,它也不会执行y=4,

而是直接停止了这样就产生了不完整的残废数据,而这个结果并不是我们想要的,

所以interrupt方法只是改变了线程的中断状态,并不会使线程停止,如果你要非要

使线程在此处停止的话,你可以使用stop方法(该方法是不建议使用的方法,

原因就是因为该方法会使线程产生不完整数据)。


isInterrupt方法的作用是:测试线程是否已经中断,如果已经中断,则返回 true;否则返回 false。

interrupted方法为一个静态方法:它的作用是测试当前线程是否已经中断,线程的中断状态 由该方法清除。

作者: 付玉光    时间: 2013-3-7 16:39
付玉光 发表于 2013-3-7 16:28
有时,真郁闷,自己提的问题,自己回答,

关于第一个问题:

完了,不知道 怎样,把主题,改为《已解决》,,羞死我了。




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2