|
这种模式,一种形像的比喻是:这是一条独木桥,能通过这座桥的只有一个人。[图一]
Single Threaded Execution Pattern是多线程程序设计的基础。

问题提出:若多个线程都擅自更改实例的状态,实例会丧失安全性。
例子:不使用Single Threaded Execution Pattern的范例。
用到三个类来测试
独木桥类
- /**
- * Bridge类,用来表示行人要通过的独木桥
- */
- package single;
- public class Bridge {
- private int counter = 0;
- private String name = "nobody";
- private String address = "nowhere";
-
- /**
- * 为通过桥的行人进行统计,并把参数传入的name与address拷贝到对应字段。
- * @param name
- * @param address
- */
- public void pass(String name,String address){
- this.counter++;
- this.name = name;
- this.address = address;
- check();
- }
-
- /**
- * 显示桥的状态
- */
- public String toString(){
- return "NO."+counter+":"+name+","+address;
- }
-
- /**
- * 检查桥的状态是否正常,如果行人的第一个字符与出生地的第一个字符不一样
- * 则表示出错,桥会损坏。
- */
- private void check(){
- if(name.charAt(0)!=address.charAt(0)){
- System.out.println("******broken******"+toString());
- }
- }
- }
复制代码
用户类
- /**
- * 用户类,表示不断过桥的行人。
- */
- package single;
- public class UserThread extends Thread {
- private final Bridge bridge;
- private final String myName;
- private final String myAddress;
-
- public UserThread(Bridge bridge,String myName,String myAddress){
- this.bridge = bridge;
- this.myName = myName;
- this.myAddress = myAddress;
- }
-
- /**
- * 覆写父类的run方法,该行人不断地过桥。
- */
- public void run(){
- System.out.println(myName+" begin");
- while(true){
- bridge.pass(myName,myAddress);
- }
- }
- }
复制代码
Main类
- /**
- * 主函数类,用来创建线程
- */
- package single;
- public class Main {
- /**
- * 创建一条桥,让三个人不断地过桥。为了编程方便,把三个人的姓名与出生地的
- 第一个字母设为相同.
- * @param args
- */
- public static void main(String[] args) {
- // TODO 自动生成方法存根
- Bridge bridge = new Bridge();
- new UserThread(bridge,"Apple","America").start();
- new UserThread(bridge,"Banana","Britain").start();
- new UserThread(bridge,"Cat","China").start();
- }
- }
复制代码
看看运行结果:的确出错了.这次运行中,当第1733157个人过桥时出错了.
- Apple begin
- Banana begin
- ******broken******NO.1733157:Banana,Britain
- Cat begin
- ******broken******NO.7468948:Banana,Britain
- ******broken******NO.8698628:Cat,America
- ******broken******NO.12099426:Cat,China
- ******broken******NO.13232825:Apple,America
- ******broken******NO.15602934:Cat,China
- ******broken******NO.28252490:Apple,America
- ******broken******NO.29486261:Banana,Britain
- ******broken******NO.35275950:Cat,China
- ******broken******NO.36112088:Banana,America
- ******broken******NO.37137157:Apple,America
复制代码
为什么会出错?
因为pass方法可被三个线程调用,pass方法的几条语句可能是交错依次执行的.
考虑两个线程的情况如下:
线程Apple 线程Banana this.name值 this.address值
this.counter++; this.counter++; (之前的值) (之前的值)
this.name=name; "Banana" (之前的值)
this.name=name; "Apple" (之前的值)
this.address=address; "Apple" "America"
this.address=address; "Apple" "Britain"
check(); check(); "Apple" "Britain"
******broken*******
[ Last edited by hjack on 2005-12-10 at 16:54 ] |
|