Java中传统的线程通信个人见解


有一个使用共同数据的经验:要用到共同数据(包括同步锁)的若干方法,要放到同一个类里。体现了程序的高内聚,也增强了程序的健壮性。

还有一个经验,把同步代码或在和锁放到共同使用的数据上,而不是放在线程内,这样的好处是什么呢:首先是更符合面向对象的思想。其次是这种设计结构非常容易实现线程的同步,并且增加线程访问共同数据的时候不用每次都在线程内增加同步代码。有利于扩展和维护。

首先看一个例子,子线程先循环10次,主线程再循环100次,接着子线程循环10次,主线程再循环100次,如此循环往复50次;

实现代码如下:

[java]
  1. public class TraditionalThreadConnection {  
  2.   
  3.     /** 
  4.      * @param args 
  5.      */  
  6.     public static void main(String[] args) {  
  7.           
  8.         final Service service = new Service();  
  9.         //子线程   
  10.         new Thread(new Runnable(){  
  11.   
  12.             @Override  
  13.             public void run() {  
  14.                 for(int i = 1;i<=50;i++){  
  15.                     service.subThread(i);  
  16.                 }  
  17.             }  
  18.               
  19.         }).start();   
  20.         //主线程   
  21.         for(int i = 1;i<=50;i++){  
  22.             service.mainThread(i);  
  23.         }  
  24.     }  
  25.       
  26.       
  27. }  
  28. class Service{  
  29.     /* 是否该子线程运行的标志 */  
  30.     private boolean isSub = true;  
  31.     public synchronized void subThread(int loop){  
  32.         //首先是判断是否该子线程运行,不是就等待   
  33.         while(!isSub){  
  34.             try {  
  35.                 this.wait();  
  36.             } catch (InterruptedException e) {  
  37.                 e.printStackTrace();  
  38.             }  
  39.         }  
  40.         for(int i=1;i<=10;i++){  
  41.             System.out.println("sub-thread-" + i + ",loop--" + loop);  
  42.         }  
  43.         isSub = false;  
  44.         //子线程运行完之后叫醒主线程   
  45.         this.notify();  
  46.     }  
  47.     public synchronized void mainThread(int loop){  
  48.         while(isSub){  
  49.             try {  
  50.                 this.wait();  
  51.             } catch (InterruptedException e) {  
  52.                 e.printStackTrace();  
  53.             }  
  54.         }  
  55.         for(int i=1;i<=100;i++){  
  56.             System.out.println("main-thread-" + i + ",loop--" + loop);  
  57.         }  
  58.         isSub = true;  
  59.         this.notify();  
  60.     }  
  61. }  

还有一点要注意的地方,就在判断是否等待的地方为什么用到while而不是if:原因是这样的,因为使用wait的时候有可能在没有调用notify的时候自己就唤醒了,开始去执行代码了,这叫做假唤醒。使用while就可以避免伪唤醒带来的灾难,还可以判断一下是否可以去执行代码。

相关内容