多線程訪問共用對象和資料的方式,多線程訪問共用對象
在多線程訪問共用對象和資料時候大致可以分為兩大類。
1:如果每個線程執行的代碼相同,可以使用同一個runnable對象,這個runnable對象中有那個共用對象。如:買票系統。
1 public class MulteThreadlShareData { 2 public static void main(String[] args) { 3 ShareData shareData = new ShareData(); 4 new Thread(shareData).start(); 5 new Thread(shareData).start(); 6 } 7 8 static class ShareData implements Runnable{ 9 int count = 100;10 @Override11 public void run() {12 while(count>0){13 decrease();14 }15 }16 public synchronized void decrease(){17 count--;18 System.out.println(Thread.currentThread().getName()+"this count: "+count);19 }20 21 }22 }
2:如果每個線程執行的代碼不相同,就要用不同的runnable對象了。這種方式又有兩種來實現這些runnable對象之間的資料共用。
- 將共用資料封裝在另一個對象中,然後將這個對象逐一傳遞給各個runnable對象中。每個線程共用資料的操作方法也分配到了這個對象身上去完成,這樣容易實現針對該資料進行共用資料的互斥和通訊。代碼實現如下:
1 public class MulteThreadlShareData2 { 2 public static void main(String[] args) { 3 final ShareData shareData = new ShareData(); 4 new Thread(new Decrease(shareData)).start(); 5 new Thread(new Increment(shareData)).start(); 6 } 7 8 static class Decrease implements Runnable{ 9 private ShareData shareData;10 public Decrease(ShareData shareData){11 this.shareData=shareData;12 }13 @Override14 public void run() {15 shareData.decrease();16 }17 18 }19 static class Increment implements Runnable{20 private ShareData shareData;21 public Increment(ShareData shareData){22 this.shareData=shareData;23 }24 @Override25 public void run() {26 shareData.increment();27 }28 29 }30 31 static class ShareData{32 int count = 100;33 public synchronized void decrease(){34 count--;35 System.out.println(Thread.currentThread().getName()+"decrease this count: "+count);36 }37 public synchronized void increment(){38 count++;39 System.out.println(Thread.currentThread().getName()+"increment this count: "+count);40 }41 }42 }
- 將這些runnable對象作為某個類的內部類,共用資料作為這個外部類的成員變數,每個線程對共用資料的操作也分配到外部類,以便實現對共用資料進行的各個操作進行互斥和通訊,作為內部類的各個runnable對象調用外部類的這些方法。
1 public class MulteThreadlShareData3 { 2 static int count = 100; 3 public static void main(String[] args) { 4 new Thread(new Decrease()).start(); 5 new Thread(new Increment()).start(); 6 7 } 8 public synchronized static void decrease(){ 9 count--;10 System.out.println(Thread.currentThread().getName()+"decrease this count: "+count);11 }12 public synchronized static void increment(){13 count++;14 System.out.println(Thread.currentThread().getName()+"increment this count: "+count);15 }16 static class Decrease implements Runnable{17 @Override18 public void run() {19 decrease();20 }21 22 }23 static class Increment implements Runnable{24 @Override25 public void run() {26 increment();27 }28 29 }30 }
- 上面兩種方式的結合:將共用資料封裝到另一個對象中,各個線程對共用資料操作的方法也分配到那個對象上去完成,對象作為外部類的成員變數或方法的局部變數,每個runnable對象作為外部類中的成員內部類或局部內部類。
1 public class MulteThreadlShareData1 { 2 public static void main(String[] args) { 3 final ShareData shareData = new ShareData(); 4 new Thread(new Runnable() { 5 @Override 6 public void run() { 7 while(true){ 8 shareData.decrease(); 9 } 10 }11 }).start();12 new Thread(new Runnable() {13 @Override14 public void run() {15 while(true){16 shareData.increment();17 }18 19 }20 }).start();21 }22 23 static class ShareData{24 int count = 100;25 public synchronized void decrease(){26 count--;27 System.out.println(Thread.currentThread().getName()+"this count: "+count);28 }29 public synchronized void increment(){30 count++;31 System.out.println(Thread.currentThread().getName()+"this count: "+count);32 }33 }34 }
總之:要同步和互斥的幾段代碼最好放在幾個獨立的方法中,這些方法在放在同一個類中,這樣容易實現他們之間的同步互斥和通訊。