多线程设计模式之(SingleThreadExecution)

多线程设计模式之(SingleThreadExecution)

要点:同一时刻只能一个线程访问共享资源
简述理解:独木桥、排它性,说白了就是加一个锁,让这个线程自己先搞定
这里自己看着教程仿着写了一个航空检票的案例(其实是有问题的),一开始是没有加锁的pass方法,想要获得一个线程不安全的运行效果,成功了,但没有完全成功,因为运行后并没有出现什么线程不安全的问题,先来看看:

/**
 *
 * 航空检查类
 */
public class FlightSecurity {

    //pass方法:比较乘客登机码(boardPass)和身份证(id)的第一个字母
    public  boolean pass(FlightTourist flightTourist,int boardCard)  {
        //一个类型的小转换
       Integer id=flightTourist.getId();
        Integer boardPass=boardCard;
        String idCard=id.toString();
        String boardPass1=boardPass.toString();
        //check开始
        if(idCard.charAt(0)==boardPass1.charAt(0)){
            System.out.println("检票号:"+boardPass1+"身份证:"+idCard+"的游客"+"通过");
            return true;
        }else if(idCard.charAt(0)!=boardPass1.charAt(0)){
            throw new RuntimeException("首字母不同");
        }
        return false;
    }
}

/**
 * 乘客类
 */
public class FlightTourist {
    //身份证
    private int id;

    FlightTourist(int id){

        this.id=id;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }
}

/**
 * 测试类
 */
public class Test extends Thread{
    //成员变量方式:乘客类和航空安全类
    private FlightSecurity flightSecurity;
    private FlightTourist flightTourist;
    private int boardCard;
    //构造
    Test(FlightTourist flightTourist,FlightSecurity flightSecurity,int boardCard){
        this.flightSecurity=flightSecurity;
        this.flightTourist=flightTourist;
        this.boardCard=boardCard;
    }

//线程
    @Override
    public void run() {
    //加个while,乘客子子孙孙无穷匮也
        while (true){
            try {
                TimeUnit.SECONDS.sleep(1);//为了更好的效果
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            flightSecurity.pass(flightTourist,boardCard);

            }
        }

    public static void main(String[] args) {
        FlightSecurity flightSecurity1=new FlightSecurity();//这里航空安全对象作为一个共享资源
        FlightTourist flightTourist=new FlightTourist(1234);//设置不同的乘客作为一个线程
        FlightTourist flightTourist1=new FlightTourist(234);
        FlightTourist flightTourist2=new FlightTourist(41234);
        FlightTourist flightTourist3=new FlightTourist(3234);
//这里设置的都是首字母相同的,为的就是能体现多线程的不安全问题
        new Test(flightTourist,flightSecurity1,1234).start();
        new Test(flightTourist1,flightSecurity1,2345).start();
        new Test(flightTourist2,flightSecurity1,45657).start();
        new Test(flightTourist3,flightSecurity1,38982).start();

    }
}

运行结果我是等了10分钟后发现还是这样:
在这里插入图片描述
表明不存在多线程不安全问题,本刚学了线程的菜鸡后来仔细找了找,发现原来其实并没有一个共享资源的存在,其实只是共享了这个对象的方法,但是并没有到共享这个对象的一个成员变量(我把成员变量给弄到局部变量里去了),所以这个线程很安全。。。。有点和ThreadLocal一样,方法的局部变量变成了一个单机版的资源。。。
在这里插入图片描述
于是将这个局部变量设置成航空安全类对象的成员变量,如下:
在这里插入图片描述
于是两个变量终于可以成为线程间的共享资源了(反省了一下,应该是我对这个共享资源理解不够深刻导致的)。改变后的运行结果如下:

在这里插入图片描述
成功体现多线程不安全问题!(具体的分析其实挺好理解的:多个线程不断对共享资源的读写,如果没有一个读写的锁机制,那么必然产生牛头不对马嘴的错误)。
那么如何解决呢,给pass方法加个锁sychronized(如果将check包装成外部方法,调用到这里依旧算是锁起来的一部分):

public synchronized boolean pass(FlightTourist flightTourist,int boardCard) 

运行结果如下:
在这里插入图片描述
线程安全,搞定!

感慨:加个锁就是这个SingleThreadExecution(莫名对这个Single有点悲哀,独木桥落寞的单身背影,唉)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值