Cicyer2513 2017-03-15 10:01 采纳率: 20%
浏览 875

关于单例和线程的奇怪问题

实现了一个存储文本的单例对象,在两个线程里不停地存入读取
单例类

 public class Singleton {
    private static Singleton defaultInstance;
    private String info="";
    private Singleton(){};
    public static Singleton getInstance(){
        if(defaultInstance==null){
            synchronized (Singleton.class) {
                if(defaultInstance==null){
                    defaultInstance=new Singleton();
                }
            }
        }
        return defaultInstance;
    }
    public String getInfo() {
        return info;
    }
    public void setInfo(String info) {
        this.info = info;
    }
}

线程类

public class singleton_thread  extends Thread{
    private String name="";
    private Singleton singleton = Singleton.getInstance();
    public singleton_thread(String string) {
        name=string; 
    }
    public Singleton getSingleton() {
        return singleton;
    }
    public void run() {

         int i=1;
         while(i<1000){
            System.out.println(name+"第"+i+"次读取:"+singleton.getInfo());
            i++;
            singleton.setInfo(name+"的第"+i+"次注入值");
         }
     }
}

测试类

public class test {

    public static void main(String[] args) {
        Singleton singleton = Singleton.getInstance();
        singleton_thread thread1= new singleton_thread("A");
        singleton_thread thread2= new singleton_thread("B");
        singleton.setInfo("确认单例:"+thread1.getSingleton().equals(thread2.getSingleton()));
        thread1.start();
        thread2.start();
    }
}

输出如下:
A第1次读取:确认单例:true
B第1次读取:确认单例:true
A第2次读取:A的第2次注入值
B第2次读取:B的第2次注入值
A第3次读取:A的第3次注入值
B第3次读取:B的第3次注入值
A第4次读取:A的第4次注入值
B第4次读取:B的第4次注入值
...
问题来了,
按这个顺序
A第2次读取:A的第2次注入值
这个时候单例的值应该是
A的第3次注入值
所以下一行应该是
B第2次读取:A的第3次注入值
但实际上是
B第2次读取:B的第2次注入值

这是为什么??

然后,在thread的while中加入sleep(10)后
输出
A第1次读取:确认单例:true
B第1次读取:确认单例:true
A第2次读取:B的第2次注入值
B第2次读取:B的第2次注入值
A第3次读取:B的第3次注入值
B第3次读取:B的第3次注入值
A第4次读取:B的第4次注入值
B第4次读取:B的第4次注入值
这个时候能对上了,说明的确存在互相覆盖,只不过ab同时在存入。B晚一点而已

那么在不sleep的时候为什么线程之间完全不互相覆盖,反而有点像是A执行完了才执行B,只不过打印的时候乱掉了。如果不是的话,是不是意味着单例是无效的?
问这个问题是担心如果是没有sleep的场景(比如用户高频率的调用spring的controller)会不会发生意想不到的情况

  • 写回答

2条回答 默认 最新

  • Ironmanzc 2017-03-15 10:13
    关注

    单例的使用
    熟悉单例的结构,适用场景

    实现要求:
    java控制台实现 每秒输出单例里面的数据和数据库里面输出的数据,并对比性能开销
    附加要求:数据库的100W条数据统计之和、数据库读出之后统计之和、内存存储数据计算之
    和 文件数据读取后统计之和(存储格式自己定义),并输出各个过程的的时间开销

    这个你会么?

    评论

报告相同问题?

悬赏问题

  • ¥15 深度学习根据CNN网络模型,搭建BP模型并训练MNIST数据集
  • ¥15 lammps拉伸应力应变曲线分析
  • ¥15 C++ 头文件/宏冲突问题解决
  • ¥15 用comsol模拟大气湍流通过底部加热(温度不同)的腔体
  • ¥50 安卓adb backup备份子用户应用数据失败
  • ¥20 有人能用聚类分析帮我分析一下文本内容嘛
  • ¥15 请问Lammps做复合材料拉伸模拟,应力应变曲线问题
  • ¥30 python代码,帮调试,帮帮忙吧
  • ¥15 #MATLAB仿真#车辆换道路径规划
  • ¥15 java 操作 elasticsearch 8.1 实现 索引的重建