一、定义
Single Threaded Execution 是指“以一个线程执行”的意思,有时也称为Critical Section(临界区)。
二、模式案例
案例:
假设三个人,频繁地通过一扇门,规定每次只能通过一个人,当通过一个人时,程序会将通过的总人次加1,同时记录该次通过人的姓名和出生地。
门.java
package Entity;
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();
}
private void check() {
if (name.charAt(0) != address.charAt(0)) {
System.out.println("*******BROKEN*******" + toString());
}
}
@Override
public String toString() {
return "Gate{" +
"counter=" + counter +
", name='" + name + '\'' +
", address='" + address + '\'' +
'}';
}
}
人.java
package Entity;
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;
}
@Override
public void run() {
System.out.println(myName + " BEGIN");
while (true) {
gate.pass(myName,myAddress);
}
}
}
main.java
import Entity.Gate;
import Entity.UserThread;
public class Demo1 {
public static void main(String[] args) {
System.out.println("Testing Gate, hit CTRL+C to exit.");
Gate gate = new Gate();
new UserThread(gate,"Alice","Alaska").start();
new UserThread(gate,"Bobby","Brazil").start();
new UserThread(gate,"Chris","Canada").start();
}
}
Testing Gate, hit CTRL+C to exit.
Alice BEGIN
Chris BEGIN
Bobby BEGIN
*******BROKEN*******Gate{counter=959, name='Alice', address='Alaska'}
*******BROKEN*******Gate{counter=1232, name='Alice', address='Alaska'}
*******BROKEN*******Gate{counter=1450, name='Alice', address='Alaska'}
*******BROKEN*******Gate{counter=1664, name='Alice', address='Alaska'}
*******BROKEN*******Gate{counter=2048, name='Alice', address='Alaska'}
*******BROKEN*******Gate{counter=2467, name='Alice', address='Alaska'}
*******BROKEN*******Gate{counter=2820, name='Bobby', address='Brazil'}
*******BROKEN*******Gate{counter=2904, name='Bobby', address='Brazil'}
*******BROKEN*******Gate{counter=3025, name='Alice', address='Alaska'}
分析:
可以看到,上述Gate类并非线程安全的,因为pass方法会被多个线程同时调用,且该方法中会修改Gate类字段的值。
优化:
package Entity;
public class Gate {
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();
}
private void check() {
if (name.charAt(0) != address.charAt(0)) {
System.out.println("*******BROKEN*******" + toString() );
}
}
@Override
public String toString() {
return "Gate{" +
"counter=" + counter +
", name='" + name + '\'' +
", address='" + address + '\'' +
'}';
}
}
三、模式讲解
角色:
Single Threaded Execution 模式的角色如下:
- SharedResource(共享资源)参与者
SharedResource就是多线程会同时访问的资源类,该类通常具有两类方法:
1、SafeMethod -- 被多个线程同时调用也不会发生问题的方法
2、UnsafeMethod -- 被多个线程同时调用会发生问题,这类方法需要加以防护,指定只能由单线程访问区域,即临界区(critical section)