如下图,多个线程访问共享数据:

多个线程访问共享数据_多个线程访问共享数据

编码应该如何实现?

举一个多线程访问共享数据的例子:设计4个线程,其中两个线程每次对j增加1,另外两个线程对j每次减少1(类似于多个窗口卖火车票)。

  1. public class MultiThreadShareData { 
  2.     private static ShareData1 data1 = new ShareData1(); 
  3.      
  4.     public static void main(String[] args) { 
  5.         ShareData1 data2 = new ShareData1(); 
  6.         new Thread(new MyRunnable1(data2)).start();//线程1 
  7.         new Thread(new MyRunnable2(data2)).start();//线程2,方法二 
  8.          
  9.         final ShareData1 data1 = new ShareData1();//共享的数据,方法一 
  10.         new Thread(new Runnable(){ 
  11.             @Override 
  12.             public void run() { 
  13.                 data1.decrement(); 
  14.             } 
  15.         }).start(); 
  16.         new Thread(new Runnable(){ 
  17.             @Override 
  18.             public void run() { 
  19.                 data1.increment(); 
  20.             } 
  21.         }).start(); 
  22.     } 
  23.      
  24.     class MyRunnable1 implements Runnable{//负责减的Runnable 
  25.         private ShareData1 data1; 
  26.         public MyRunnable1(ShareData1 data1){ 
  27.             this.data1 = data1; 
  28.         } 
  29.         public void run() { 
  30. while(true){
                    data1.decrement(); 
  31. }
  32.          
  33.         } 
  34.     } 
  35.      
  36.     class MyRunnable2 implements Runnable{//负责加的Runnable 
  37.         private ShareData1 data1; 
  38.         public MyRunnable2(ShareData1 data1){ 
  39.             this.data1 = data1; 
  40.         } 
  41.         public void run() { 
  42. while(true){
                    data1.increment();
  43. }
  44.         } 
  45.     } 
  46.  
  47.     class ShareData1 /*implements Runnable*/
  48. /*      private int count = 100;//多窗口卖票 
  49.         @Override 
  50.         public void run() { 
  51.             while(true){ 
  52.                 count--; 
  53.             } 
  54.         }*/ 
  55.          
  56.         private int j = 0
  57.         //该线程实现的是每次加1,synchronized实现互斥 
  58.         public synchronized void increment(){ 
  59.             j++; 
  60.         } 
  61.         public synchronized void decrement(){//该线程实现的是每次减1 
  62.             j--; 
  63.         } 
  64.     } 

总结:

  • 如果每个线程执行的代码相同可以使用同一个Runnable对象,这个Runnable对象中有那个共享的数据,例如上面的注释部分,卖票系统可以这么做。
  • 如果每个线程执行的代码不同,这时候需要不同的Runnable对象,有以下两种方式来实现这些Runnable对象之间的数据共享:

方法一:将共享数据封装在另外一个对象中,然后将这个对象逐一传递给各个Runnable对象,每隔线程对共享数据的操作方法也分配到那个对象身上完成,这样容易实现针对该数据进行的各个操作的互斥和通信。如上面的方法2。

方法:将这些Runnable对象作为某一个类中的内部类,共享数据作为这个外部类中的成员变量,每个线程对共享数据的操作方法也分配给外部类,以便实现对共享数据进行的各个操作的互斥和通信,作为内部类的各个Runnable对象调用外部类的这些方法。如上面的方法1。