多线程之Single Threaded Execution 模式

 

创建三个类:

类名 说明
Main 创建一个门,让三个人不断的通过门
Gate 表示门的类,穿过一个人时记录名字和出生地
UserThread 表示人的类。人们不断通过门
public class Main {
    public static void main(String[] args) {
        System.out.println("Testing Gate, go ");
        Gate gate = new Gate();
        new UserThread(gate,"Alice","Aalska").start();
        new UserThread(gate,"Bobby","Brazuk").start();
        new UserThread(gate,"Chris","Canada").start();

    }
}
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();
    }

    @Override
    public String toString() {
        return "Gate{" +
                "counter=" + counter +
                ", name='" + name + '\'' +
                ", address='" + address + '\'' +
                '}';
    }

    private void check() {
        if (name.charAt(0) != address.charAt(0)){
            System.out.println("*** BROKEN *** " + toString());
        }

    }
public class UserThread extends  Thread {

    private  final  Gate gate;
    private final String myname;
    private final String myadress;

    public UserThread(Gate gate,String myname,String myadress) {
        this.gate = gate;
        this.myadress = myadress;
        this.myname = myname;
    }


    public void run() {
        System.out.println(myname + " Begin");
        while (true){
            gate.pass(myname,myadress);
        }
    }
}

运行结果:多线程之Single Threaded Execution 模式_第1张图片

我们的本意是名字的首字母和地址的首字母不相同时才打印BROKEN的信息,结果并不是我们想的这样,即使首字母都相同,还是会打印出来。

一个门 ,被多个人使用时,也就出现了安全隐患。

Gate类的实例被多个线程使用时,也就是说着个门是共享资源,运行结果与预期不一致,这个Gate类是不安全的,是非线程安全类。

我们先看看最主要的门的方法:

public  void pass(String name,String address){
    this.counter++;
    this.name = name;
    this.address = address;
    check();
}

这个方法记录的是每个人经过时,门要记录的某个人的名字和地址。设想一下,如果两个人同时经过这个门,现在有两个名字和两个地址,而门一次性只能记一个人的信息,因此也就发生了安全隐患。要解决这个问题的根本就是一个门只能让一个人经过。

我们只要修改这个门的类的pass方法:

 

再运行看看:

多线程之Single Threaded Execution 模式_第2张图片

 

无论多久都不会打印***BROKEN***

synchronized这个关键字修饰的方法意味着该方法同时只能由一个线程执行。也就是一个门,同时只能让一个人经过。

 

Single Threaded Execution 模式中的登场角色

角色:SharedResource(共享资源)

Gate类其实就是扮演SharedResource角色,SharedResource角色是可以被多个线程调用的类,这个类有很多方法,无非两种,

第一种是多个线程调用会发生问题的方法,第二种就是多个线程调用不会发生问题的方法。

我们所要解决的就是第一种方法:通过在方法前加synchronized关键字,就起到了这个方法同时只能让一个线程调用的目的,确保程序的安全性。

哪些场景使用:

1 多个线程访问时

当然,如果所有的线程都是完全独立操作的,那也无需用此模式,这种状态称为线程互不干涉。在某些处理多线程的框架中,线程的独立性是由框架内部控制的,这时使用者也就无需顾忌安全隐患,正常处理你的业务即可。

2 状态有可能发生变化时

如果在创建实例后,实例的状态再也不会发生变化,那就无需使用此模式。后续介绍的Immutable(不可变) 模式中,实例的状态不会发生变化,自然也就无需使用synchronized方法。

3 需要确保安全性时

只有在需要确保安全性时,才需要此模式。

例如Java的集合类大多数都是非线程安全的。这是为了不需要考虑安全性时提高程序的运行速度。

如果要使用安全的集合,Java提供了以下方法可确保集合类为线程安全的。

Collections是java.util.下的一个集合工具类

多线程之Single Threaded Execution 模式_第3张图片

 

 

 

 

你可能感兴趣的:(多线程,并发)