java SingleThreadedExecution

SingleThreadedExecution

SingleThreadedExecution意思就是以一个线程执行,就像独木桥同时只允许一个人同行一样,该模式用于设置限制,以确保同一时间内只能让一个线程执行处理。

Single Threaded Execution有时候也称为临界区(critical section)或临界域(critical region)。Single Thread Execution这个名称侧重于执行处理的线程(过桥的人),而临界区或临界域的名称则侧重于执行范围(人过的桥)。

不使用Single Threaded Execution模式的程序

假设三个人频繁地通过一个只允许一个人经过的门的情形,当人们通过门的时候,统计人数会递增。另外,程序还会记录通行者的“姓名和出生地”。

创建一个门Gate,让三个人UserThread不断的通过。首先main创建一个Gate类的实例,并将该实例作为参数传给UserThread类的构造函数,告诉人们“可通过这个门”。

非线程安全的Gate类

public class Gate {
    private int counter = 0;
    private String name = "Nobody";
    private String address = "Nowhere";
    public void pass(String name,String address){
        this.counter++;
        this.name = name;
        this.address = address;
         check();
    }

    public String toString(){
        return "No."+counter +":"+name+","+address;
    }
    public void check(){
        if(name.charAt(0)!=address.charAt(0)){
            System.out.println("***************BROKEN**************"+toString());
        }
    }
}

UserThread类,表示的是不断通过的人。实现thread类。

public class UserThread extends Thread {
    private final Gate gate;
    private final String myname;
    private final String myaddress;
    public UserThread(Gate gate, String myname, String myaddress) {
        this.gate = gate;
        this.myname = myname;
        this.myaddress = myaddress;
    }
    public void run(){
        System.out.println(myname + "BEGIN");
        while (true){
            gate.pass(myname,myaddress);
        }
    }
}

测试:

    @Test
    public void testUserThread(){
        System.out.println("开始执行:");
        Gate gate = new Gate();
        new UserThread(gate,"Alice","Alaska").start();
        new UserThread(gate,"Bobby","Brazil").start();
        new UserThread(gate,"Chris","Canada").start();
    }

运行结果:

开始执行:
AliceBEGIN
BobbyBEGIN
ChrisBEGIN
***************BROKEN**************No.141359:Chris,Canada
***************BROKEN**************No.141831:Bobby,Canada 错误
***************BROKEN**************No.141870:Bobby,Canada 错误
***************BROKEN**************No.141906:Bobby,Brazil
***************BROKEN**************No.141958:Alice,Alaska
***************BROKEN**************No.141993:Alice,Canada 错误
***************BROKEN**************No.142023:Alice,Canada 错误
***************BROKEN**************No.142056:Alice,Alaska
***************BROKEN**************No.143358:Chris,Canada

注意通行错误的情况。此处就出现了线程不安全状态。再看应该正确的地方有的首字母相同却依然显示出来了 。导致这种原因的是多个线程无线pass改写了name和address显示虽然名字和地址相同但是做判断的时候却不一定相同。

而名字和地址不同的情况如下如下:

this.counter++;
this.name = name;
this.address = address;
check();

此处只考虑两个线程执行pass方法,这四条语句就可能交错执行,name还没赋值address已经赋其他值。这时就会显示错误信息。

线程安全Gate

将pass和toString方法修改为synchronized方法。这样之前BROKEN就不会再次出现了。

public class GateSyn {
    private int counter = 0;
    private String name = "Nobody";
    private String address = "Nowhere";
    public synchronized void pass(String name,String address){
        this.counter++;
        this.name = name;
        this.address = address;
        check();
    }

    public synchronized String toString(){
        return "No."+counter +":"+name+","+address;
    }
    public void check(){
        if(name.charAt(0)!=address.charAt(0)){
            System.out.println("***************BROKEN**************"+toString());
        }
    }
}

此处线程要执行sybchronized时,必须获取this的锁,而能够获取一个实例的锁的线程只有一个。正式因为这种唯一性,才能使得synchronized来实现Single Threaded Execu模式。

阅读更多
换一批

没有更多推荐了,返回首页