注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

东东的博客

江南烟雨,同大家一起分享

 
 
 

日志

 
 

JAVA线程之六:线程的通信  

2010-07-02 11:49:35|  分类: java相关 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
虽然经常创建多个不相同的线程来完成不相关的任务,然而有时执行的任务可能有一定联系,这样就需要使这些线程进行交互。比如有一个水塘,其中对水塘 操作无非包括“进水”和“排水”,这两个行为各自代表一个线程,当水塘中没有水时,“排水”行为不能再进行;当水塘水满时,“进水”行为不能再进行。
      在Java中用于线程间通信的方法是在前文中提到过的wait()与notify()方法,拿水塘的例子来说明,线程A代表“进水”,线程B代表“排水 ”,这两个线程对水塘都具有访问权限。假设线程B试图做“排水”行为,然而水塘中却没有水。这时候线程B只好等待一会。可以使用如下控制:
if(water.isEmpty)
{
       water.wait();
}
在 由线程A将水塘注水之前,线程B不能从这个队列中释放,它不能再次运行。当线程A将水注入水塘中后,应该由线程A来通知线程序B水塘中已经被注入水了,线 程B才可以运行。此时,水塘中等待队列中的第一个被阻塞的线程在队列中被释放出来,并且可以重新加入竞争。可以使用如下控制:
water.setValue(String water)
water.notify();
在此将“进水”与“排水”抽象为线程A,线程B。“水塘”抽象为线程A与线程B的共享对象water,上述情况即可看作线程通信。

      线程通信可以使用wait()与notify()方法。notify()方法最多只能释放等待队列中的第一个线程,如果有多个线程在等 待,可以使用notifyAll()方法,释放所有线程。另外,wait()方法除了可以被notify()方法调用终止以外,还可以通过调用线程的 interrupt()方法来中断,前文中已经提到过,通过调用线程的interrupt()方法来终止,wait()方法会抛出一个异常。因此,如同 sleep()方法,也需要将wait()方法放在try/catch语句块中。
      在实际应用中,wait()与notify()方法 必须在同步方法或同步块中调用,因为只有获得这个共享对象,才可能释放它。为了使线程对一个对象调用wait()或notiry()方法,线程必须锁定那 个特定的对象,这个时候就需要同步机制进行保护。举例如下:
 (1)以水塘为例,下面是在同步机制保护下调用wait()方法的代码片段。
synchronized(water){
      try

      {
            if(water.isEmpty())

            {
                   water.wait();               //线程调用wait()方法
             }
       }catch(InterruptException e)

       {
              ……//省略异常处理代码
        }
}
代码说明:当“排水”线程得到对水塘的控制权时,即拥有了water这个对象,但水塘中却没有水,此时,water.isEmpty()条件满足,water对象被释放,所以“排水”线程在等待。
 (2)下面是在同步机制下调用notify()方法的程序代码片段。
synchronized(water)

{
       water.notify();                    //线程调用notify()方法
}
代码说明:notify()方法通知“排水”线程,并将其唤醒,notify()方法与wait()方法相同,都需要在同步方法或同步块中才能被调用。当“进水”线程将水注入水塘后,再通知等待的“排水”线程,告诉它可以排水了,“排水”线程被唤醒后继续做排水工作。
 (3)完整代码:src\com\wsy\TxThread.java完整代码:
package com.wsy;
class Water

{//水塘类
       static Object water=new Object();
       static int total=6;//假设水塘总共可以含水量为6
       static int mqsl=3;//假设水塘中拥有含水量为3
       static int ps=0;//假设水塘目前排水量为0
}
class ThreadA extends Thread

{//排水类
       void pswork()

       {
              synchronized(Water.water)  

             {
                    System.out.println("水塘是否没有水: "+isEmpty());
                    if(isEmpty())

                    {
                           try

                          {
                                 Water.water.wait();
                           }catch(InterruptedException e)

                          {
                                 e.printStackTrace();
                           }
                     }
                     else

                     {
                             Water.ps++;
                             System.out.println("水塘目前排水水量 "+Water.ps);
                      }
               }
        }
        public void run()

       {
              while(Water.mqsl<Water.total)

              {
                     if(isEmpty())
                           System.out.println("水塘目前没有水,排水线程被挂起");
                     System.out.println("排水工作开始");
                     pswork();
                     try

                     {
                            sleep(1000);
                     }catch(InterruptedException e)

                     {
                             e.printStackTrace();
                      }
                }
         }
         public boolean isEmpty()

         {
                 return Water.mqsl==Water.ps?true:false;
         }
}
class ThreadB extends Thread

{//进水类
        void jswork()

       {
               synchronized(Water.water)

              {
                      Water.mqsl++;//假设水塘每小时进水量为1
                      Water.water.notify();
                      System.out.println("水塘目前进水量为 "+Water.mqsl);
               }
        }
        public void run()

        {
                while(Water.mqsl<Water.total)

               {
                       System.out.println("进水工作开始");
                       jswork();
                       try

                       {
                              sleep(3000);
                        }catch(InterruptedException e)

                       {
                              e.printStackTrace();
                        }
                }
         }
}
public class TxThread

{
       public static void main(String[] args)

       {
               ThreadA threadA=new ThreadA();
               ThreadB threadB=new ThreadB();
               threadB.start();
               threadA.start();
        }

}

执行结果:
进水工作开始
排水工作开始
水塘是否没有水: false
水塘目前排水水量 1
水塘目前进水量为 4
排水工作开始
水塘是否没有水: false
水塘目前排水水量 2
排水工作开始
水塘是否没有水: false
水塘目前排水水量 3
进水工作开始
水塘目前进水量为 5
排水工作开始
水塘是否没有水: false
水塘目前排水水量 4
排水工作开始
水塘是否没有水: false
水塘目前排水水量 5
水塘目前没有水,排水线程被挂起
排水工作开始
水塘是否没有水: true
进水工作开始
水塘目前进水量为 6
但该结果不唯一。需要说明的是Water.water,类名.成员变量。这是静态类的用法,静态类是static的,不能实例化,非静态类一般需要实例化后才可以操作,才能访问类中的方法。


转自:http://blog.csdn.net/zhandoushi1982/archive/2010/04/21/5511187.aspx

  评论这张
 
阅读(591)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2018