黑马程序员技术交流社区

标题: 多线程,join方法 [打印本页]

作者: 史政法    时间: 2013-2-22 13:22
标题: 多线程,join方法
  1. class  Demo implements Runnable
  2. {
  3.         public synchronized void run()
  4.         {
  5.                 try
  6.                 {
  7.                         wait();
  8.                 }
  9.                 catch (InterruptedException e)
  10.                 {
  11.                 }
  12.                 for (int x = 0;x<70 ;x++ )
  13.                 {
  14.                         System.out.println(Thread.currentThread().getName()+"..."+x);
  15.                 }
  16.         }
  17. }

  18. class  JoinDemo
  19. {
  20.         public static void main(String[] args) throws Exception
  21.         {
  22.                 Demo d = new Demo();
  23.                 Thread t1 = new Thread(d);
  24.                 Thread t2 = new Thread(d);
  25.                 t1.start();
  26.                 //t2.start();
  27.                 t1.join();
  28.                 //t1.interrupt();
  29.                 //t2.start();
  30.                 for (int x = 0;x<80 ;x++ )
  31.                 {
  32.                         System.out.println("main..."+x);
  33.                 }
  34.                 System.out.println("Over!");
  35.         }
  36. }
复制代码
谁能写个main把权限释放给了t1,然后t1被冻结了,然后利用interrupt方法清除main冻结状态的方法,可以加入其他线程。主要是为了理解wait和interrupt方法。

作者: 罗海云    时间: 2013-2-22 13:30
在JDK1.0中,可以用stop方法来终止,但是现在这种方法已经被禁用了,改用interrupt方法。

Thread.interrupt()方法不会中断一个正在运行的线程。它的作用是,在线程受到阻塞时抛出一个中断信号,这样线程就得以退出阻塞的状态。更确切的说,如果线程被Object.wait, Thread.join和Thread.sleep三种方法之一阻塞,那么,它将接收到一个中断异常(InterruptedException),从而提早地终结被阻塞状态。

interrupt方法并不是强制终止线程,它只能设置线程的interrupted状态,而在线程中一般使用一下方式:
while (!Thread.currentThread().isInterrupted() && more work to do)

{...}

而被block的线程(sleep() or join())在被调用interrupt时会产生InterruptException,此时是否终止线程由本线程自己决定。程序的一般形式是:
public void run()
{
try
{
. . .
while (!Thread.currentThread().isInterrupted() && more work to do)
{
do more work
}
}
catch(InterruptedException e)
{
// thread was interrupted during sleep or wait
}
finally
{
cleanup, if required
}
// exiting the run method terminates the thread
}

Thread.sleep方法也会产生InterruptedException,因此,如果每次在做完一些工作后调用了sleep方法,那么就不用检查isInterrupted,而是直接捕捉InterruptedException。

---------------------------------------------------------------------------------------

假如我们有一个任务如下,交给一个Java线程来执行,如何才能保证调用interrupt()来中断它呢?

class ATask implements Runnable{  
  
    private double d = 0.0;  
      
    public void run() {  
        //死循环执行打印"I am running!" 和做消耗时间的浮点计算  
        while (true) {  
            System.out.println("I am running!");  
              
            for (int i = 0; i < 900000; i++) {  
                d =  d + (Math.PI + Math.E) / d;  
            }  
            //给线程调度器可以切换到其它进程的信号  
            Thread.yield();  
        }  
    }  
}  
  
public class InterruptTaskTest {  
      
    public static void main(String[] args) throws Exception{  
        //将任务交给一个线程执行  
        Thread t = new Thread(new ATask());  
        t.start();  
         
        //运行一断时间中断线程  
        Thread.sleep(100);  
        System.out.println("****************************");  
        System.out.println("Interrupted Thread!");  
        System.out.println("****************************");  
        t.interrupt();  
    }  
}   


运行这个程序,我们发现调用interrupt()后,程序仍在运行,如果不强制结束,程序将一直运行下去,如下所示:
......  
I am running!  
I am running!  
I am running!  
I am running!  
****************************  
Interrupted Thread!  
****************************  
I am running!  
I am running!  
I am running!  
I am running!  
I am running!  
....  

虽然中断发生了,但线程仍然在进行,离开线程有两种常用的方法:
抛出InterruptedException和用Thread.interrupted()检查是否发生中断,

作者: 贾文泽    时间: 2013-2-22 16:08
没明白楼主的意思,帖子的标题是多线程,join方法, 又说主要是为了理解wait和interrupt方法。。。。???能具体点么?
作者: 史政法    时间: 2013-2-23 05:23
贾文泽 发表于 2013-2-22 16:08
没明白楼主的意思,帖子的标题是多线程,join方法, 又说主要是为了理解wait和interrupt方法。。。。??? ...

因为join,所以主函数把执行权释放给了t1了,t1又被冻结了,然后用interrupt方法解冻,让程序能够结束,,不知道要怎么写。当然是因为对wait和interrupt方法还不够了解了。
作者: 贾文泽    时间: 2013-2-23 09:13
  1. class StopThread implements Runnable{
  2.         private boolean flag = true;
  3.         public synchronized void run(){
  4.                 while(flag){
  5.                         try{
  6.                                 wait();              //t1线程等待,等待main线程调用t1.interrupt();强制让t1恢复到运行状态,并抛出中断异常
  7.                         }
  8.                         catch (InterruptedException e){
  9.                                
  10.                                 System.out.println(Thread.currentThread().getName()+"...."+e.toString());
  11.                                 flag = false;         //改变标记,结束循环,也就是结束run方法,结束线程
  12.                         }
  13.                         System.out.println(Thread.currentThread().getName()+"......run");
  14.                 }
  15.         }
  16.         public void setFlag(){
  17.                 flag = false;
  18.         }
  19. }
  20. public class StopThreadDemo {
  21.         public static void main(String[] args) {
  22.                 StopThread st = new StopThread();

  23.                 Thread t1 = new Thread(st);
  24.                
  25.                 t1.start();
  26.                  
  27. //                try{
  28. //                        t1.join();        //这句代码会使主线程等待,直到t1线程结束,但是t1进入run方法为等待状态,而main线程又不能继续执行,
  29. //                                                                不能调用interrupt方法,所以如果将调用t1.join(); t1又进入等待状态,那么这个程序无法结束
  30. //                }catch(InterruptedException e){
  31. //                        System.out.println(Thread.currentThread().getName()+"...."+e.toString());
  32. //                }

  33.                 int num = 1;
  34.                 while(true){
  35.                         if(++num==50){
  36.                                 //清除t1的冻结状态。
  37.                                 t1.interrupt();     //强制让t1线程恢复到运行状态,并抛出中断异常,从而结束run方法,结束线程
  38.                                 break;
  39.                         }
  40.                         System.out.println(Thread.currentThread().getName()+"....."+num);
  41.                 }
  42.                 System.out.println("over");
  43.         }
  44. }
复制代码
最后我大概按我的理解说下 wait 和 interrupt 方法
wait();     当对象执行这个方法时,线程被阻塞,暂时停止运行,直到其他线程执行这个对象的notify()或者notifyAll()唤醒为止,当前线程在等待唤醒时或者等待唤醒前获得中断信息时,
              抛出InterruptedException,唤醒后的线程会继续对导致该线程被提醒的条件进行测试,如果条件不满足,则继续等待,所有需要wait()发挥作用的代码总是在循环中
  1. synchronized(obj){
  2.         while(<条件不满足>){
  3.                 obj.wait();
  4.         }
  5.         ...//条件满足时的代码
  6. }
复制代码
interrupt 方法:
     对于线程的停止,从原理上说,只有一种方法,run方法结束,即线程结束,往往都是通过操作标记控制循环使 run 方法结束,但是当线程处于冻结状态,并且没有指定的方式让该线程恢复到运行状态,这时需要调用 interrupt() 方法清除冻结状态,强制使线程恢复到正常运行状态,并抛出一个中断信息,所有说,interrupt方法对正常运行的线程是不起作用的,也就是当线程被 Obj.wait(),Theard.joiin, Theard.sleep, 这三个方法之一阻塞,那么该线程会收到一个 InterruptedException异常,从而提早的终结被阻塞状态
    正因为对一个线程调用interrupt()后只是改变了他的中断状态,线程可以继续执行下去,在没有调用sleep,wait,join 等方法或自己抛出异常之前,他就可以调用interrupted()来清除中断状态(恢复原状)。 interrupted()方法会检查当前线程的中断状态,如果为‘被中断状态’则改变当前线程为‘非中断状态’并返回true,如果为‘非中断状态’则返回false。

作者: 朱玉玺    时间: 2013-2-23 16:21
你join之后,启动主线程内join之后,t1线程一直在等待,所以主线程的代码都没法执行了,可把join改成join(1000)。貌似这个问题之前看过啊。
作者: 史政法    时间: 2013-2-24 07:04
贾文泽 发表于 2013-2-23 09:13
最后我大概按我的理解说下 wait 和 interrupt 方法
wait();     当对象执行这个方法时,线程被阻塞,暂时停 ...

非常感谢,很详细,异常的地方不是太了解,我的理解是:wait()方法里定义的有异常代码,一旦等待状态被interrupt()方法清除,就会抛出一个异常信息,可以抛出或使用try() ,catch()来进行解决,,,,,

我不明白的是interrupte()方法里应该是怎么定义的呢?为什么说:强制使线程恢复到正常运行状态,并抛出一个中断信息,也就是说这句话应该怎么去理解呢?或者说他里面的代码应该是什么样子的呢?如果线程在调用 Object 类的 wait()、wait(long) 或 wait(long, int) 方法,或者该类的 join()、join(long)、join(long, int)、sleep(long) 或 sleep(long, int) 方法过程中受阻,则其中断状态将被清除,它还将收到一个 InterruptedException。
作者: 贾文泽    时间: 2013-2-24 12:59
史政法 发表于 2013-2-24 07:04
非常感谢,很详细,异常的地方不是太了解,我的理解是:wait()方法里定义的有异常代码,一旦等待状态被in ...

这个我也没有看过方法里面具体怎么写的,只能按照我的理解跟你说下,希望对你的理解有帮助。

       对线程的InterruptedException【中断异常】也就是线程在阻塞阶段收到一个中断信号,可能为了安全起见,线程自身对这种中断信号不做处理【以前的stop方法可以强制杀掉线程,后来遭反对停用了】,应该是语言设计者让程序检测如果线程在阻塞状态下接受到中断信号,那么就抛出一个InterruptedException,并且清除中断信号,让线程继续执行,由catch代码块捕获处理
       而对象的Interrupt()方法则是像该线程【阻塞状态中】发送了一个中断信号。只是在线程中设置了一个中断标记,表明了一种中断请求,这个标记如果生效,就必须在run()方法中被检测到,之后就跟上面一样了,抛出一个InterruptedException,并且清除中断信号,让线程继续执行【Interrupt()方法强制让线程恢复到运行状态】,由catch代码块捕获处理





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