栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

JAVA多线程设计模式篇 2、Single Threaded Execution 模式——这一刻,我的眼里只有你

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

JAVA多线程设计模式篇 2、Single Threaded Execution 模式——这一刻,我的眼里只有你

文章目录

1.孙悟空去了高老庄?

1.1 定义师父类1.2 定义徒弟类1.3 师父发现不对劲了 2.问题出现在哪?

2.1 问题2.2 完善2.3 问题二 3.注意事项总结

1.孙悟空去了高老庄?

悟空、八戒跟师父请假要回去探亲。师父要求每个人请假要填上姓名、目的地。
弟子们很老实遵照执行,然而,当过了一段时间出了问题。我们看看问题出在哪里。

1.1 定义师父类

师父提供了一个方法 请假(姓名,目的地),即public void notice(String name, String address)。为避免出错,师父类定义了一个私有检查方法,看请假的情况有没有问题。

public class Master {
    private int cnt = 0;
    private String name;
    private String address;

    public synchronized void notice(String name, String address) {
        this.name = name;
        this.address = address;
        cnt++;
        check();
    }

    private void check() {
        if (name.equals("孙悟空") && (!address.equals("花果山")))
            System.out.println("第"+cnt+" 次出现问题:" + name + "," + address);
        if (name.equals("猪八戒") && (!address.equals("高老庄")))
            System.out.println("第"+cnt+" 次出现问题:" + name + "," + address);
    }
}
1.2 定义徒弟类

徒弟很老实,在定义自己信息的时候都用上了final,担心数据被篡改。
徒弟线程类启动后将不断向师父请假。

public class Follower extends Thread {

    private final Master master;
    private final String name;
    private final String address;

    public Follower(Master master,String name,String address){
        this.master = master;
        this.name = name;
        this.address = address;
    }

    @Override
    public void run() {
        while (true) {
            master.notice(name,address);
        }
    }
}
1.3 师父发现不对劲了

在运行过程中,师父的check()方法,发现了不一致的情况。

public class Main {
    public static void main(String[] args) {
        Master master = new Master();
        Follower sunwukong = new Follower(master,"孙悟空","花果山");
        Follower zhubajie = new Follower(master,"猪八戒","高老庄");
        sunwukong.start();
        zhubajie.start();
    }
}

运行结果:

第379950712 次出现问题:孙悟空,花果山
第379956315 次出现问题:孙悟空,高老庄
2.问题出现在哪?

经过一番检查。我们发现Master类是不安全的。

    出现问题:孙悟空,花果山 。这个是正常的啊。为什么还是报错?
    出现问题:孙悟空,高老庄 这个又是怎么产生的呢,明明悟空类的地址是花果山啊。
2.1 问题

观察这几个代码,由于没有同步机制,在多线程环境中是交替执行的,也就是说A B 线程会不断有可能交替覆盖name和address属性。

        this.name = name;
        this.address = address;
        cnt++;
        check();
2.2 完善

将Master的public void notice(String name, String address) 方法更改为同步方法。
经过synchronized方法同步后,出问题的四行代码被打包为一个原子方法。一次性只允许一个徒弟请假,请假的过程中不会出现交替运行的情况,

public synchronized void notice(String name, String address) 

运行很久都没有报错。

2.3 问题二

为什么check方法不需要增加synchronized同步?
因为第一、check()只被notice()调用,而notice方法已经同步了。第二、check()是私有方法,外部无法调用,且内部就只被notice()调用。

3.注意事项

在Single Threaded Execution 模式中,需要仔细找出实例状态不稳定的范围,将这个范围设置为临界区进行保护,同一时间只允许一个线程执行。

总结

在使用多线程环境中,如果共享资源的状态有可能会发生变化,那么更改资源状态的方法很可能就是不安全方法。对于这些方法应该加锁同步,加以保护。

多线程系列在github上有一个开源项目,本系列博客的实验代码都在里面。

https://github.com/forestnlp/concurrentlab

如果您对软件开发、机器学习、深度学习有兴趣请关注本博客,将持续推出Java、软件架构、深度学习相关专栏。

您的支持是对我最大的鼓励。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/771295.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号