1. 问题的提出:
仿真程序,花园委员会希望了解每天通过多个大门进入公园的总人数。每个大门都有一个计数器,并且每个十字转门的计数值递增时,就表示公园中的总人数的共享计数值也会递增。
2.例1
package
jiangning.c21;
import
java.util.ArrayList;
import
java.util.List;
import
java.util.Random;
import
java.util.concurrent.ExecutorService;
import
java.util.concurrent.Executors;
import
java.util.concurrent.TimeUnit;
class
Count{
//计数器
private
int
count
= 0;
private
Random
rand
=
new
Random(47);
//引入rand的目的是在重count读取到 temp中,
// 到 temp递增并把temp存回到count中留出大概一半的时间,如果将increment方法的
// synchronized关键字注释掉,这个程序将会崩溃,多个任务同时访问并修改count。
public
synchronized
int
increment(){
//增加人员,同步用来控制count域的访问
// 如果移除synchronized将会发现count和number不符。
int
temp =
count
;
if
(
rand
.nextBoolean()){
Thread. yield();
}
return
(
count
= ++temp);
}
public
synchronized
int
value(){
//同步用来控制count域的访问
return
count
;
}
}
class
Entrance
implements
Runnable{
private
static
Count
count
=
new
Count();
private
static
List<Entrance>
entrances
=
new
ArrayList<Entrance>();
private
int
number
= 0;
private
final
int
id
;
private
static
volatile
boolean
canceled
=
false
;
//因为canceled被定义为volatile,
// boolean标记,它只会被读取和赋值,所以不需要同步,就可以安全的访问。在开发中对这样的
// 域有疑问,那么就用synchronized。
public
static
void
cancel(){
canceled
=
true
;
}
public
Entrance (
int
id){
this
.
id
= id;
entrances
.add(
this
);
}
public
void
run(){
while
(!
canceled
){
//在run方法中使得number值进行递增。每个Entrance对象维护一个number
synchronized
(
this
){
++
number
;
}
System.
out
.println(
this
+
" Total "
+
count
.increment());
//在run方法count值进行递增。
try
{
TimeUnit.
MILLISECONDS
.sleep(100);
}
catch
(InterruptedException e) {
System.
out
.println(
"sleep interrupted"
);
}
}
System.
out
.println(
"Stopping "
+
this
);
}
public
synchronized
int
getValue(){
return
number
;
}
public
String toString(){
return
"Entance "
+
id
+
": "
+ getValue();
}
public
static
int
getTotalCount(){
return
count
.value();
}
public
static
int
sumEntrance(){
int
sum = 0;
for
(Entrance e :
entrances
){
sum = sum + e.getValue();
}
return
sum;
}
}
public
class
OrnamentalGarden {
public
static
void
main(String[] args)
throws
Exception{
ExecutorService exec = Executors. newCachedThreadPool();
for
(
int
i=0; i<5; i++){
exec.execute(
new
Entrance(i));
}
TimeUnit.
SECONDS
.sleep(3);
//暂停3秒
Entrance. cancel();
//将canceled设置为true
exec.shutdown();
//关闭线程。
if
(!exec.awaitTermination(250, TimeUnit.
MICROSECONDS
)){
//等待每个任务结束
// 如果所有的任务在超时时间之前结束,则返回true,否则返回false,表示不是说有的任
// 务已经结束。
System.
out
.println(
"Some task were not terminated!"
);
}
System.
out
.println(
"Total: "
+ Entrance.getTotalCount ());
System.
out
.println(
"Sum of Entrance : "
+ Entrance.sumEntrance());
}
}
/**
*
Entance
1:
1
Total
2
Entance
4:
1
Total
5
Entance
2:
1
Total
3
Entance
3:
1
Total
4
Entance
0:
1
Total
1
Entance
1:
2
Total
6
Entance
0:
2
Total
10
Entance
2:
2
Total
9
Entance
4:
2
Total
7
Entance
3:
2
Total
8
Entance
2:
3
Total
11
Entance
0:
3
Total
15
Entance
1:
3
Total
13
Entance
3:
3
Total
14
Entance
4:
3
Total
12
Entance
1:
4
Total
16
Entance
0:
4
Total
20
Entance
3:
4
Total
19
Entance
4:
4
Total
17
Entance
2:
4
Total
18
Entance
1:
5
Total
21
Entance
2:
5
Total
25
Entance
0:
5
Total
23
Entance
4:
5
Total
24
Entance
3:
5
Total
22
Entance
3:
6
Total
26
Entance
1:
6
Total
27
Entance
0:
6
Total
29
Entance
2:
6
Total
28
Entance
4:
6
Total
30
Entance
1:
7
Total
31
Entance
2:
7
Total
35
Entance
4:
7
Total
34
Entance
3:
7
Total
33
Entance
0:
7
Total
32
Entance
1:
8
Total
36
Entance
4:
8
Total
40
Entance
2:
8
Total
38
Entance
3:
8
Total
37
Entance
0:
8
Total
39
Entance
2:
9
Total
41
Entance
3:
9
Total
42
Entance
0:
9
Total
43
Entance
4:
9
Total
44
Entance
1:
9
Total
45
Entance
1:
10
Total
46
Entance
3:
10
Total
50
Entance
0:
10
Total
47
Entance
2:
10
Total
49
Entance
4:
10
Total
48
Entance
3:
11
Total
51
Entance
2:
11
Total
55
Entance
1:
11
Total
54
Entance
4:
11
Total
52
Entance
0:
11
Total
53
Entance
4:
12
Total
56
Entance
1:
12
Total
60
Entance
2:
12
Total
59
Entance
0:
12
Total
57
Entance
3:
12
Total
58
Entance
3:
13
Total
61
Entance
1:
13
Total
65
Entance
2:
13
Total
63
Entance
4:
13
Total
62
Entance
0:
13
Total
64
Entance
0:
14
Total
66
Entance
4:
14
Total
70
Entance
2:
14
Total
69
Entance
1:
14
Total
68
Entance
3:
14
Total
67
Entance
4:
15
Total
71
Entance
3:
15
Total
72
Entance
1:
15
Total
73
Entance
0:
15
Total
75
Entance
2:
15
Total
74
Entance
0:
16
Total
76
Entance
3:
16
Total
80
Entance
2:
16
Total
79
Entance
4:
16
Total
77
Entance
1:
16
Total
78
Entance
3:
17
Total
81
Entance
2:
17
Total
84
Entance
1:
17
Total
85
Entance
0:
17
Total
83
Entance
4:
17
Total
82
Entance
0:
18
Total
86
Entance
3:
18
Total
88
Entance
1:
18
Total
90
Entance
4:
18
Total
87
Entance
2:
18
Total
89
Entance
4:
19
Total
91
Entance
2:
19
Total
92
Entance
1:
19
Total
93
Entance
3:
19
Total
95
Entance
0:
19
Total
94
Entance
2:
20
Total
96
Entance
3:
20
Total
97
Entance
4:
20
Total
100
Entance
0:
20
Total
99
Entance
1:
20
Total
98
Entance
1:
21
Total
101
Entance
4:
21
Total
105
Entance
2:
21
Total
104
Entance
0:
21
Total
103
Entance
3:
21
Total
102
Entance
1:
22
Total
106
Entance
4:
22
Total
110
Entance
0:
22
Total
109
Entance
2:
22
Total
108
Entance
3:
22
Total
107
Entance
1:
23
Total
111
Entance
3:
23
Total
115
Entance
2:
23
Total
114
Entance
0:
23
Total
113
Entance
4:
23
Total
112
Entance
3:
24
Total
116
Entance
2:
24
Total
117
Entance
0:
24
Total
120
Entance
1:
24
Total
119
Entance
4:
24
Total
118
Entance
1:
25
Total
121
Entance
4:
25
Total
125
Entance
2:
25
Total
124
Entance
0:
25
Total
123
Entance
3:
25
Total
122
Entance
1:
26
Total
126
Entance
2:
26
Total
127
Entance
4:
26
Total
130
Entance
3:
26
Total
128
Entance
0:
26
Total
129
Entance
1:
27
Total
131
Entance
4:
27
Total
132
Entance
3:
27
Total
133
Entance
2:
27
Total
134
Entance
0:
27
Total
135
Entance
4:
28
Total
136
Entance
2:
28
Total
139
Entance
0:
28
Total
138
Entance
3:
28
Total
137
Entance
1:
28
Total
140
Entance
0:
29
Total
141
Entance
2:
29
Total
145
Entance
4:
29
Total
144
Entance
3:
29
Total
143
Entance
1:
29
Total
142
Entance
4:
30
Total
146
Entance
3:
30
Total
150
Entance
2:
30
Total
149
Entance
0:
30
Total
147
Entance
1:
30
Total
148
Some
task
were
not
terminated!
Total:
150
Sum
of
Entrance
:
150
Stopping
Entance
3:
30
Stopping
Entance
2:
30
Stopping
Entance
0:
30
Stopping
Entance
1:
30
Stopping
Entance
4:
30
*/
在复审并发代码时,要格外小心。