十六、JAVA多线程笔记:Single Thread Execution设计模式

这里有一座独木桥。因为桥身非常的细,一次只能允许一个人通过。当这个人没有下桥,另一个人就不能过桥。如果桥上同时又两个人,桥就会因为无法承重而破碎而掉落河里。 这就是Single Threaded Execution。有时也称为Critical section(临界区)。

这个模式用来限制同时只允许一个线程运行。

机场过安检

1.非线程安全

代码:

package com.zl.step16.flight;

public class FlightSecurity {

    private  int count = 0 ;
    // 登机牌
    private  String boardingPass = "null" ;
    // 身份证
    private  String idCard =  "null" ;


    // 通过安检信息
    public void pass(String boardingPass , String idCard){
        this.boardingPass = boardingPass ;
        this.idCard = idCard ;
        this.count ++;
        check();
    }

    // 安全检查
    private void check() {
        // 简单测试,当登机牌和身份证首字母不相同时,则表示检查不通过 仅为测试,别较真。。。。
        if(boardingPass.charAt(0) != idCard.charAt(0)){
            throw   new RuntimeException("=====Exeception============"+ toString()) ;
        }

    }

    @Override
    public String toString() {
        return "The" + count+ " passengers , boardingPass["+boardingPass+"] , idCard ["+idCard+"]。";
    }

}
package com.zl.step16.flight;

public class FlightSecurityTest {

    static class Passengers extends Thread{
        private final FlightSecurity flightSecurity ;

        // 身份证
        private final String idCard ;

        // 登机牌
        private final String boardingPass ;

        // 构造旅客对象
        public Passengers(FlightSecurity flightSecurity , String idCard ,String boardingPass){
            this.flightSecurity = flightSecurity ;
            this.idCard = idCard ;
            this.boardingPass  = boardingPass ;
        }

        @Override
        public void run(){
            while (true){
                // 不断通过安检
                flightSecurity.pass(boardingPass,idCard);
            }
        }

    }

    public static void main(String[] args) {
        final FlightSecurity flightSecurity = new FlightSecurity() ;

        new Passengers(flightSecurity,"A11","A21").start();

        new Passengers(flightSecurity,"B12","B22").start();

        new Passengers(flightSecurity,"B13","B23").start();



    }




}

异常信息:

问题分析:

1.首字母相同,却无法通过安检

2.首字母不同现象:

线程安全:

修改pass方法: 增加 synchronized 关键字即可

什么时候适合Single Thread Execution设计模式

1.多线程访问资源的时候,被synchronized同步的方法总是排他性的。

2.多个线程对某个类的状态发生改变的时候

吃面问题:

演示交叉锁导致程序死锁的情况:

package com.zl.step16.noodle;

public class Tableware {
    //餐具名称
    private final String toolName ;

    public Tableware(String toolName){
        this.toolName= toolName ;
    }

    @Override
    public String toString(){
        return "Tool: "+toolName ;
    }


}
package com.zl.step16.noodle;

public class EatNoodleThread extends Thread {
    private final String name ;

    //左手边的餐具
    private final Tableware leftTool ;


    private final Tableware rightTool ;

    public EatNoodleThread(String name ,Tableware leftTool , Tableware rightTool ){
        this.name = name ;
        this.leftTool = leftTool ;
        this.rightTool = rightTool ;
    }


    @Override
    public void run(){
        while (true){
            this.eat();
        }
    }

    private void eat() {
        synchronized (leftTool){
            System.out.println(name + "take up "+ leftTool +" (left)" );
            synchronized (rightTool){
                System.out.println(name + "take up "+ rightTool +" (right)" );

                System.out.println(name + "is eating now." );

                System.out.println(name + "put down "+rightTool +" (right)" );
            }

            System.out.println(name + "put down "+rightTool +" (left)" );

        }


    }


}
package com.zl.step16.noodle;

public class EatNoodleThreadTest {
    public static void main(String[] args) {
        Tableware fork = new Tableware("fork") ;
        Tableware knife = new Tableware("knife") ;

        new EatNoodleThread("A" , fork ,knife).start();


        new EatNoodleThread("B" , fork ,knife).start();


        new EatNoodleThread("C" , fork ,knife).start();



        new EatNoodleThread("D" , fork ,knife).start();


        new EatNoodleThread("E" , fork ,knife).start();



    }
}

解决:

主要问题:交叉锁导致两个线程之间互相等待彼此释放持有的锁。

代码:

package com.zl.step16.noodle;

public class Tableware {
    //餐具名称
    private final String toolName ;

    public Tableware(String toolName){
        this.toolName= toolName ;
    }

    @Override
    public String toString(){
        return "Tool: "+toolName ;
    }


}
package com.zl.step16.noodle;

public class TableWarePair {



    //左手边的餐具
    private final Tableware leftTool ;


    private final Tableware rightTool ;

    public  TableWarePair(  Tableware leftTool , Tableware rightTool ){

        this.leftTool = leftTool ;
        this.rightTool = rightTool ;

    }


    public Tableware getLeftTool() {
        return leftTool;
    }

    public Tableware getRightTool() {
        return rightTool;
    }
}
package com.zl.step16.noodle;

public class EatNoodleThread extends Thread {
    private final String name ;

    private final TableWarePair tableWarePair ;


    public EatNoodleThread(String name , TableWarePair tableWarePair ){
        this.name = name ;
        this.tableWarePair = tableWarePair ;

    }



    @Override
    public void run(){
        while (true){
            this.eat();
        }
    }

    private void eat() {
        synchronized (tableWarePair){
            System.out.println(currentThread().getName() + " : " + name + " take up "+ tableWarePair.getLeftTool() +" (left)" );

            System.out.println(currentThread().getName() + " : " + name + " take up "+ tableWarePair.getRightTool() +" (right)" );

            System.out.println(currentThread().getName() + " : " + name + " is eating now." );

            System.out.println(currentThread().getName() + " : " + name + " put down "+tableWarePair.getRightTool() +" (right)" );


            System.out.println(currentThread().getName() + " : " + name + " put down "+tableWarePair.getLeftTool() +" (left)" );

        }


    }


}
package com.zl.step16.noodle;

public class EatNoodleThreadTest {
    public static void main(String[] args) {
        Tableware fork = new Tableware("fork") ;
        Tableware knife = new Tableware("knife") ;


        TableWarePair tableWarePair = new TableWarePair(fork,knife) ;

        new EatNoodleThread("A" , tableWarePair).start();


        new EatNoodleThread("B" , tableWarePair).start();





    }
}

猜你喜欢

转载自blog.csdn.net/zhanglong_4444/article/details/86238059