这是一个在并发状态下对共享资源的多线程访问。这些访问必须是互斥的进行,因为涉及到对资源的修改。假设现在销售火车票。目的地有
3
个,分别是北京,天津和上海。使用一个枚举类型表示。
Destation.java
package
com.zj.tickets;
public
enum
Destation {
BEIJING
,
SHANGHAI
,
TIANJING
}
|
下面设计车票类,
final
int
original
表示车票基数;
int
current
表示当前还有多少张票;
Destation
destation
表示目的地,它必须从上面的枚举型中取出其一。
Ticket.java
package
com.zj.tickets;
public
class
Ticket {
private
final
int
original
;
private
int
current
;
private
final
Destation
destation
;
public
Ticket(
int
nums, Destation where) {
current
=
original
= nums;
destation
= where;
}
public
int
degress() {
return
--
current
;
}
public
int
original() {
return
original
;
}
public
boolean
soldout() {
return
current
<= 0;
}
public
Destation getDestation() {
return
destation
;
}
public
int
getCurrent() {
return
current
;
}
}
|
下面设计售票厅类,
Map<Destation, Ticket>
tickets
表示目前可销售的车票种类,它通过一个
static
块初始化。
Map<Destation, Integer>
records
是当前售票厅的火车票销售情况。
List<BookingOffice>
offices
表示当前可工作的所有售票厅,每个售票厅是一个线程。
int
ticketsSold
表示当前售票厅售出的火车票总数。
int
id
表示当前售票厅编号。
每个线程都会模拟客户买票、工作人员查询数据库和售票交易过程。
模拟的数据为,当前发往北京、上海和天津的火车票各
5
张;每个售票厅交易
5
次(无论交易成功或失败)后关闭。
BookingOffice.java
package
com.zj.tickets;
import
java.util.ArrayList;
import
java.util.HashMap;
import
java.util.List;
import
java.util.Map;
import
java.util.Random;
import
java.util.concurrent.TimeUnit;
public
class
BookingOffice
implements
Runnable {
private
static
Map<Destation, Ticket>
tickets
=
new
HashMap<Destation, Ticket>();
private
Map<Destation, Integer>
records
;
private
static
List<BookingOffice>
offices
=
new
ArrayList<BookingOffice>();
private
int
ticketsSold
= 0;
private
final
int
id
;
// now today's tickets for sell:
static
{
tickets
.put(Destation.
BEIJING
,
new
Ticket(5, Destation.
BEIJING
));
tickets
.put(Destation.
SHANGHAI
,
new
Ticket(5, Destation.
SHANGHAI
));
tickets
.put(Destation.
TIANJING
,
new
Ticket(5, Destation.
TIANJING
));
}
public
BookingOffice(
int
id) {
this
.
id
= id;
offices
.add(
this
);
resetRecords();
}
private
void
resetRecords() {
records
=
new
HashMap<Destation, Integer>();
}
private
void
addRecords(Destation d) {
Integer freq =
records
.get(d);
records
.put(d, freq ==
null
? 1 : freq + 1);
}
public
void
run() {
int
transaction = 5;
while
(transaction-- > 0) {
// simulate a customer's coming:
Destation d = Destation.values()[
new
Random().nextInt(Destation
.values().
length
)];
print(
this
+
"i want a ticket for "
+ d);
// simulate the officer's checking:
try
{
TimeUnit.
SECONDS
.sleep(1);
}
catch
(InterruptedException e) {
e.printStackTrace();
}
// simulate the transaction:
Ticket wanted =
tickets
.get(d);
synchronized
(
wanted
) {
if
(!wanted.soldout()) {
print(
this
+
"sold a ticket for "
+ d);
wanted.degress();
addRecords(d);
++
ticketsSold
;
print(
this
+
""
+ d +
" tickets still have "
+ wanted.getCurrent());
}
else
print(
this
+
"tickets for "
+ d +
" have been sold out."
);
}
}
print(
this
+
"closed"
);
print(
this
+
"totally sold tickets:"
+
ticketsSold
+
",sell records:"
+
records
);
}
public
synchronized
int
getValue() {
return
ticketsSold
;
}
public
String toString() {
return
"<Officce-"
+
id
+
">"
;
}
static
void
print(String s) {
System.
out
.println(s);
}
}
|
模拟售票过程如下,启动
5
个售票厅。
Sell.java
package
com.zj.tickets;
import
java.util.concurrent.ExecutorService;
import
java.util.concurrent.Executors;
public
class
Sell {
public
static
void
main(String[] args)
throws
Exception {
ExecutorService exec = Executors.newCachedThreadPool();
for
(
int
i = 0; i < 5; i++)
exec.execute(
new
BookingOffice(i));
exec.shutdown();
}
}
|
结果:
<Officce-0>i want a ticket for BEIJING
<Officce-1>i want a ticket for SHANGHAI
<Officce-2>i want a ticket for TIANJING
<Officce-3>i want a ticket for SHANGHAI
<Officce-4>i want a ticket for SHANGHAI
<Officce-0>sold a ticket for BEIJING
<Officce-0>BEIJING tickets still have 4
<Officce-0>i want a ticket for TIANJING
<Officce-1>sold a ticket for SHANGHAI
<Officce-1>SHANGHAI tickets still have 4
<Officce-1>i want a ticket for SHANGHAI
<Officce-2>sold a ticket for TIANJING
<Officce-2>TIANJING tickets still have 4
<Officce-2>i want a ticket for BEIJING
<Officce-3>sold a ticket for SHANGHAI
<Officce-3>SHANGHAI tickets still have 3
<Officce-3>i want a ticket for TIANJING
<Officce-4>sold a ticket for SHANGHAI
<Officce-4>SHANGHAI tickets still have 2
<Officce-4>i want a ticket for BEIJING
<Officce-4>sold a ticket for BEIJING
<Officce-4>BEIJING tickets still have 3
<Officce-4>i want a ticket for SHANGHAI
<Officce-3>sold a ticket for TIANJING
<Officce-3>TIANJING tickets still have 3
<Officce-3>i want a ticket for TIANJING
<Officce-2>sold a ticket for BEIJING
<Officce-2>BEIJING tickets still have 2
<Officce-2>i want a ticket for BEIJING
<Officce-1>sold a ticket for SHANGHAI
<Officce-1>SHANGHAI tickets still have 1
<Officce-1>i want a ticket for SHANGHAI
<Officce-0>sold a ticket for TIANJING
<Officce-0>TIANJING tickets still have 2
<Officce-0>i want a ticket for SHANGHAI
<Officce-4>sold a ticket for SHANGHAI
<Officce-4>SHANGHAI tickets still have 0
<Officce-4>i want a ticket for BEIJING
<Officce-3>sold a ticket for TIANJING
<Officce-3>TIANJING tickets still have 1
<Officce-3>i want a ticket for BEIJING
<Officce-2>sold a ticket for BEIJING
<Officce-2>BEIJING tickets still have 1
<Officce-2>i want a ticket for SHANGHAI
<Officce-1>tickets for SHANGHAI have been sold out.
<Officce-1>i want a ticket for SHANGHAI
<Officce-0>tickets for SHANGHAI have been sold out.
<Officce-0>i want a ticket for SHANGHAI
<Officce-4>sold a ticket for BEIJING
<Officce-4>BEIJING tickets still have 0
<Officce-4>i want a ticket for BEIJING
<Officce-3>tickets for BEIJING have been sold out.
<Officce-3>i want a ticket for BEIJING
<Officce-2>tickets for SHANGHAI have been sold out.
<Officce-2>i want a ticket for SHANGHAI
<Officce-1>tickets for SHANGHAI have been sold out.
<Officce-1>i want a ticket for BEIJING
<Officce-0>tickets for SHANGHAI have been sold out.
<Officce-0>i want a ticket for SHANGHAI
<Officce-4>tickets for BEIJING have been sold out.
<Officce-4>closed
<Officce-4>totally sold tickets:4,sell records:{BEIJING=2, SHANGHAI=2}
<Officce-3>tickets for BEIJING have been sold out.
<Officce-3>closed
<Officce-3>totally sold tickets:3,sell records:{TIANJING=2, SHANGHAI=1}
<Officce-2>tickets for SHANGHAI have been sold out.
<Officce-2>closed
<Officce-2>totally sold tickets:3,sell records:{BEIJING=2, TIANJING=1}
<Officce-1>tickets for BEIJING have been sold out.
<Officce-1>closed
<Officce-1>totally sold tickets:2,sell records:{SHANGHAI=2}
<Officce-0>tickets for SHANGHAI have been sold out.
<Officce-0>closed
<Officce-0>totally sold tickets:2,sell records:{BEIJING=1, TIANJING=1}
本文转自zhangjunhd51CTO博客,原文链接:http://blog.51cto.com/zhangjunhd/70767,如需转载请自行联系原作者