多個線程訪問共享對象和數據的方式有兩種情況:
1、每個線程執行的代碼相同,例如,賣票:多個窗口同時賣這100張票,這100張票需要多個線程共享。
2、每個線程執行的代碼不同,例如:設計四個線程,其中兩個線程每次對j增加1,另外兩個線程每次對j減少1。
a、如果每個線程執行的代碼相同,可以使用同一個Runnable對象,這個對象中有共享數據。賣票就可以這樣做,每個窗口都在做賣票任務,賣的票都是同一個數據(點擊查看具體案例)。
b、如果每個線程執行的代碼不同,就需要使用不同的Runnable對象,有兩種方式實現Runnable對象之間的數據共享:
1)、將共享數據單獨封裝到一個對象中,同時在對象中提供操作這些共享數據的方法,可以方便實現對共享數據各項操作的互斥和通信。
2、)將各個Runnable對象作為某個類的內部類,共享數據作為外部類的成員變量,對共享數據的操作方法也在外部類中提供,以便實現互斥和通信,內部類的Runnable對象調用外部類中操作共享數據的方法即可。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
|
package com.ljq.test.thread; /** * 多個線程之間共享數據的方式 * * 設計四個線程,其中兩個線程每次對j增加1,另外兩個線程每次對j減少1。循環100次。 * * @author Administrator * */ public class MultiThreadShareData { private static ShareData data1 = new ShareData(); public static void main(String[] args) { ShareData data2 = new ShareData(); new Thread( new DecrementRunnable(data2)).start(); new Thread( new IncrementRunnable(data2)).start(); final ShareData data1 = new ShareData(); new Thread( new Runnable() { @Override public void run() { data1.decrement(); } }).start(); new Thread( new Runnable() { @Override public void run() { data1.increment(); } }).start(); } } /** * 創建線程類,負責對j減少1 * * @author Administrator * */ class DecrementRunnable implements Runnable { private ShareData data; public DecrementRunnable(ShareData data) { this .data = data; } public void run() { for ( int i= 0 ; i< 100 ; i++){ data.decrement(); } } } /** * 創建線程類,負責對j增加1 * * @author Administrator * */ class IncrementRunnable implements Runnable { private ShareData data; public IncrementRunnable(ShareData data) { this .data = data; } public void run() { for ( int i= 0 ; i< 100 ; i++){ data.increment(); } } } /** * 封裝共享數據 * * @author Administrator * */ class ShareData { private int j = 0 ; /** * 每次對j增加1 */ public synchronized void increment() { j++; System.out.println( "j++=" +j); } /** * 每次對j減少1 */ public synchronized void decrement() { j--; System.out.println( "j--=" +j); } } |
注意:要同步互斥的幾段代碼最好分別放在幾個獨立的方法中,這些方法再放在同一個類中,這樣比較容易實現它們之間的同步互斥和通信。