多线程_线程间通讯

5.1.5  线程间通信

 

wait:

notify();

notifyAll();

 

都使用在同步中,因为要对持有监视器(锁)的线程操作。

所以要使用在同步中,因为只有同步才具有锁。

 

为什么这些操作线程的方法要定义Object类中呢?

因为这些方法在操作同步中线程时,都必须要标识它们所操作线程只有的锁,

只有同一个锁上的被等待线程,可以被同一个锁上notify唤醒。

不可以对不同锁中的线程进行唤醒。

 

也就是说,等待和唤醒必须是同一个锁。

 

而锁可以是任意对象,所以可以被任意对象调用的方法定义Object类中。

 

练习一:线程间通信

 

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. class Res  
  2. {  
  3.          String name;  
  4.          String sex;  
  5.          boolean flag = false;  
  6. }  
  7.    
  8. class Input implements Runnable  
  9. {  
  10.          private Res r ;  
  11.          Input(Resr)  
  12.          {  
  13.                    this.r= r;  
  14.          }  
  15.          public void run()  
  16.          {  
  17.                    int x = 0;  
  18.                    while(true)  
  19.                    {  
  20.                             synchronized(r)  
  21.                             {  
  22.    
  23.                                      if(r.flag)  
  24.                                                try{r.wait();}catch(Exceptione){}  
  25.                                      if(x==0)  
  26.                                      {  
  27.                                                r.name="mike";  
  28.                                                r.sex="man";  
  29.                                      }  
  30.                                      else  
  31.                                      {  
  32.                                                r.name="丽丽";  
  33.                                                r.sex= "女女女女女";  
  34.                                      }  
  35.                                      x = (x+1)%2;  
  36.                                       r.flag = true;  
  37.                                      r.notify();  
  38.                             }  
  39.                    }  
  40.          }  
  41. }  
  42.    
  43. class Output implements Runnable  
  44. {  
  45.          private Res r ;  
  46.           
  47.          Output(Resr)  
  48.          {  
  49.                    this.r= r;  
  50.          }  
  51.          public void run()  
  52.          {  
  53.                    while(true)  
  54.                    {  
  55.                             synchronized(r)  
  56.                             {  
  57.                                      if(!r.flag)  
  58.                                      try{r.wait();}catch(Exceptione){}  
  59.                                      System.out.println(r.name+"...."+r.sex);  
  60.                                      r.flag= false;  
  61.                                      r.notify();  
  62.                             }  
  63.                    }  
  64.          }  
  65. }  
  66.    
  67. class InputOutputDemo  
  68. {  
  69.          public static void main(String[] args)  
  70.          {  
  71.                    Res r = new Res();  
  72.    
  73.                    Input in = new Input(r);  
  74.                    Output out = new Output(r);  
  75.    
  76.                    Thread t1 = new Thread(in);  
  77.                    Thread t2 = new Thread(out);  
  78.    
  79.                    t1.start();  
  80.                    t2.start();  
  81.          }  
  82. }  


 

练习二:练习一的优化后

 

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. class Res  
  2. {  
  3.          private String name;  
  4.          private String sex;  
  5.          private boolean flag = false;  
  6.    
  7.          public synchronized void set(String name,String sex)  
  8.          {  
  9.                    if(flag)  
  10.                             try{this.wait();}catch(Exceptione){}//this.wait()中说明这里的锁是this  
  11.                    this.name= name;  
  12.                     
  13.                    this.sex= sex;  
  14.                    flag= true;  
  15.                    this.notify();  
  16.          }  
  17.          public synchronized void out()  
  18.          {  
  19.                    if(!flag)  
  20.                    try{this.wait();}catch(Exceptione){} //this.wait()中说明这里的锁是this  
  21.                    System.out.println(name+"........"+sex);  
  22.                    flag= false;  
  23.                    this.notify();  
  24.          }  
  25. }  
  26.    
  27. class Input implements Runnable  
  28. {  
  29.          private Res r ;  
  30.          Input(Resr)  
  31.          {  
  32.                    this.r= r;  
  33.          }  
  34.          public void run()  
  35.          {  
  36.                    intx = 0;  
  37.                    while(true)  
  38.                    {  
  39.                             if(x==0)                                  
  40.                                      r.set("mike","man");                                    
  41.                             else   
  42.                                      r.set("丽丽","女女女女女");                              
  43.                             x= (x+1)%2;  
  44.                    }  
  45.          }  
  46. }  
  47.    
  48. class Output implements Runnable  
  49. {  
  50.          private Res r ;  
  51.           
  52.          Output(Resr)  
  53.          {  
  54.                    this.r= r;  
  55.          }  
  56.          public void run()  
  57.          {  
  58.                    while(true)  
  59.                    {  
  60.                             r.out();  
  61.                    }  
  62.          }  
  63. }  
  64.    
  65.    
  66. class InputOutputDemo2  
  67. {  
  68.          public static void main(String[] args)  
  69.          {  
  70.                    Resr = new Res();  
  71.    
  72.                    newThread(new Input(r)).start();  
  73.                    newThread(new Output(r)).start();  
  74.                    //上面两句是下面六句话的简化写法  
  75.                    /* 
  76.                    Inputin = new Input(r); 
  77.                    Outputout = new Output(r); 
  78.   
  79.                    Threadt1 = new Thread(in); 
  80.                    Threadt2 = new Thread(out); 
  81.   
  82.                    t1.start(); 
  83.                    t2.start(); 
  84.                    */  
  85.          }  
  86. }  


 

练习二:多个生产者消费者

 

 

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. class ProducerConsumerDemo  
  2. {  
  3.          public static void main(String[] args)  
  4.          {  
  5.                    Resourcer = new Resource();  
  6.    
  7.                    Producer pro = new Producer(r);  
  8.                    Consumer con = new Consumer(r);  
  9.    
  10.                    Thread t1 = new Thread(pro);  
  11.                    Thread t2 = new Thread(pro);  
  12.                    Thread t3 = new Thread(con);  
  13.                    Thread t4 = new Thread(con);  
  14.    
  15.                    t1.start();  
  16.                    t2.start();  
  17.                    t3.start();  
  18.                    t4.start();  
  19.    
  20.          }  
  21. }  
  22.    
  23. /* 
  24. 对于多个生产者和消费者。 
  25. 为什么要定义while判断标记。 
  26. 原因:让被唤醒的线程再一次判断标记。 
  27.   
  28.   
  29. 为什么定义notifyAll, 
  30. 因为需要唤醒对方线程。 
  31. 因为只用notify,容易出现只唤醒本方线程的情况。导致程序中的所有线程都等待。 
  32.   
  33. */  
  34.    
  35.    
  36. class Resource  
  37. {  
  38.          private String name;  
  39.          private int count = 1;  
  40.          private boolean flag = false;  
  41.                             //  t1   t2  
  42.          public synchronized void set(String name)  
  43.          {  
  44.                    while(flag)  
  45.                             try{this.wait();}catch(Exceptione){}//t1(放弃资格)  t2(获取资格)  
  46.                    this.name= name+"--"+count++;  
  47.    
  48.                    System.out.println(Thread.currentThread().getName()+"...生产者.."+this.name);  
  49.                    flag= true;  
  50.                    this.notifyAll();  
  51.          }  
  52.    
  53.    
  54.          //  t3  t4   
  55.          public synchronized void out()  
  56.          {  
  57.                    while(!flag)  
  58.                             try{wait();}catch(Exceptione){}//t3(放弃资格) t4(放弃资格)  
  59.                    System.out.println(Thread.currentThread().getName()+"...消费者........."+this.name);  
  60.                    flag= false;  
  61.                    this.notifyAll();  
  62.          }  
  63. }  
  64.    
  65. class Producer implements Runnable  
  66. {  
  67.          private Resource res;  
  68.    
  69.          Producer(Resourceres)  
  70.          {  
  71.                    this.res= res;  
  72.          }  
  73.          publicvoid run()  
  74.          {  
  75.                    while(true)  
  76.                    {  
  77.                             res.set("+商品+");  
  78.                    }  
  79.          }  
  80. }  
  81.    
  82. class Consumer implements Runnable  
  83. {  
  84.          private Resource res;  
  85.    
  86.          Consumer(Resourceres)  
  87.          {  
  88.                    this.res= res;  
  89.          }  
  90.          public void run()  
  91.          {  
  92.                    while(true)  
  93.                    {  
  94.                             res.out();  
  95.                    }  
  96.          }  
  97. }  


 

5.1.6  JDK1.5 中提供了多线程升级解决方案。Lock

 

将同步Synchronized替换成现实Lock操作。

将Object中的wait,notify notifyAll,替换了Condition对象。

该对象可以Lock锁进行获取。

该示例中,实现了本方只唤醒对方操作。

 

Lock:替代了Synchronized

         lock

         unlock

         newCondition()

 

Condition:替代了Object wait notify notifyAll

         await();

         signal();

         signalAll();

 

练习四:用JDK1.5 新特性 Lock来练习多个生产者和消费者

 

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. import java.util.concurrent.locks.*;  
  2.    
  3. class ProducerConsumerDemo2  
  4. {  
  5.          public static void main(String[] args)  
  6.          {  
  7.                    Resource r = new Resource();  
  8.    
  9.                    Producer pro = new Producer(r);  
  10.                    Consumer con = new Consumer(r);  
  11.    
  12.                    Thread t1 = new Thread(pro);  
  13.                    Thread t2 = new Thread(pro);  
  14.                    Thread t3 = new Thread(con);  
  15.                    Thread t4 = new Thread(con);  
  16.    
  17.                    t1.start();  
  18.                    t2.start();  
  19.                    t3.start();  
  20.                    t4.start();  
  21.    
  22.          }  
  23. }  
  24.    
  25. class Resource  
  26. {  
  27.          private String name;  
  28.          private int count = 1;  
  29.          private boolean flag = false;  
  30.                             //  t1   t2  
  31.          private Lock lock = new ReentrantLock();  
  32.    
  33.          private Condition condition_pro = lock.newCondition();  
  34.          private Condition condition_con = lock.newCondition();  
  35.    
  36.    
  37.    
  38.          public  void set(String name)throwsInterruptedException  
  39.          {  
  40.                    lock.lock();  
  41.                    try  
  42.                    {  
  43.                             while(flag)  
  44.                                      condition_pro.await();//t1,t2  
  45.                             this.name= name+"--"+count++;  
  46.    
  47.                             System.out.println(Thread.currentThread().getName()+"...生产者.."+this.name);  
  48.                             flag= true;  
  49.                             condition_con.signal();//唤醒condition_con  
  50.                    }  
  51.                    finally  
  52.                    {  
  53.                             lock.unlock();//释放锁的动作一定要执行。  
  54.                    }  
  55.          }  
  56.    
  57.    
  58.          //  t3  t4   
  59.          public  void out()throws InterruptedException  
  60.          {  
  61.                    lock.lock();  
  62.                    try  
  63.                    {  
  64.                             while(!flag)  
  65.                                      condition_con.await();  
  66.                             System.out.println(Thread.currentThread().getName()+"...消费者........."+this.name);  
  67.                             flag= false;  
  68.                             condition_pro.signal();//唤醒condition_pro  
  69.                    }  
  70.                    finally  
  71.                    {  
  72.                             lock.unlock();  
  73.                    }  
  74.                     
  75.          }  
  76. }  
  77.    
  78. class Producer implements Runnable  
  79. {  
  80.          private Resource res;  
  81.    
  82.          Producer(Resourceres)  
  83.          {  
  84.                    this.res= res;  
  85.          }  
  86.          public void run()  
  87.          {  
  88.                    while(true)  
  89.                    {  
  90.                             try  
  91.                             {  
  92.                                      res.set("+商品+");  
  93.                             }  
  94.                             catch(InterruptedException e)  
  95.                             {  
  96.                             }  
  97.                              
  98.                    }  
  99.          }  
  100. }  
  101.    
  102. class Consumer implements Runnable  
  103. {  
  104.          privateResource res;  
  105.    
  106.          Consumer(Resourceres)  
  107.          {  
  108.                    this.res= res;  
  109.          }  
  110.          public void run()  
  111.          {  
  112.                    while(true)  
  113.                    {  
  114.                             try  
  115.                             {  
  116.                                      res.out();  
  117.                             }  
  118.                             catch(InterruptedException e)  
  119.                             {  
  120.                             }  
  121.                    }  
  122.          }  
  123. }  


 

5.1.7停止线程

 

定义循环结束标记

因为线程运行代码一般都是循环,只要控制了循环即可。

使用interrupt(中断)方法。

该方法是结束线程的冻结状态,使线程回到运行状态中来。

注:stop方法已经过时不再使用。

 

stop方法已经过时。

 

如何停止线程?

只有一种,run方法结束。

开启多线程运行,运行代码通常是循环结构。

 

只要控制住循环,就可以让run方法结束,也就是线程结束。

 

 

特殊情况:

当线程处于了冻结状态。

就不会读取到标记。那么线程就不会结束。

 

当没有指定的方式让冻结的线程恢复到运行状态是,这时需要对冻结进行清除。

强制让线程恢复到运行状态中来。这样就可以操作标记让线程结束。

 

Thread类提供该方法 interrupt();

 

练习五:如何停止线程

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. class StopThread implements Runnable  
  2. {  
  3.          private boolean flag =true;  
  4.          public  void run()  
  5.          {  
  6.                    while(flag)  
  7.                    {  
  8.                             System.out.println(Thread.currentThread().getName()+"....run");  
  9.                    }  
  10.          }  
  11.          public void changeFlag()  
  12.          {  
  13.                    flag= false;  
  14.          }  
  15. }  
  16.    
  17. class StopThreadDemo  
  18. {  
  19.          public static void main(String[] args)  
  20.          {  
  21.                    StopThread st = new StopThread();  
  22.                     
  23.                    Thread t1 = new Thread(st);  
  24.                    Thread t2 = new Thread(st);  
  25.    
  26.                    t1.setDaemon(true);//守护线程_属于后台线程  
  27.                    t2.setDaemon(true);//守护线程  
  28.                    t1.start();  
  29.                    t2.start();  
  30.    
  31.                    int num = 0;  
  32.    
  33.                    while(true)  
  34.                    {  
  35.                             if(num++== 60)  
  36.                             {  
  37.                                      //st.changeFlag();  
  38.                                      //t1.interrupt();  
  39.                                      //t2.interrupt();  
  40.                                      break;  
  41.                             }  
  42.                             System.out.println(Thread.currentThread().getName()+"......."+num);  
  43.                    }  
  44.                    System.out.println("over");  
  45.          }  
  46. }  


 

 

练习六:用匿名内部类创建两种线程

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. class ThreadTest  
  2. {  
  3.          public static void main(String[] args)  
  4.          {  
  5.                     
  6.                    new Thread()  
  7.                    {  
  8.                             public void run()  
  9.                             {  
  10.                                      for(intx=0; x<100; x++)  
  11.                                      {  
  12.                                                System.out.println(Thread.currentThread().getName()+"....."+x);  
  13.                                      }  
  14.                             }  
  15.                    }.start();  
  16.                     
  17.    
  18.    
  19.                    for(intx=0; x<100; x++)  
  20.                    {  
  21.                             System.out.println(Thread.currentThread().getName()+"....."+x);  
  22.                    }  
  23.    
  24.                    Runnable r  = new Runnable()  
  25.                    {  
  26.                             public void run()  
  27.                             {  
  28.                                      for(intx=0; x<100; x++)  
  29.                                      {  
  30.                                                System.out.println(Thread.currentThread().getName()+"....."+x);  
  31.                                      }  
  32.                             }  
  33.                    };  
  34.                    new Thread(r).start();  
  35.          }  
  36. }  


 

5.1.8  Thread类中一些常用的方法

setDaemon(boolean on)
将该线程标记为守护线程或用户线程。

 

join() 
等待该线程终止。

 

yield() 
暂停当前正在执行的线程对象,并执行其他线程。

 

setPriority(int newPriority)
更改线程的优先级。

         MAX_PRIORITY

         线程可以具有的最高优先级。

MIN_PRIORITY

         线程可以具有的最低优先级。

NORM_PRIORITY

         分配给线程的默认优先级

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值