繁体   English   中英

单例,线程和同步

[英]Singleton, threads and synchronization

我正在关注《 Head First设计模式》(第5章,单例模式)。

他们谈论的线程的重叠进入方法getInstance()时, synchronized不使用关键字。

我如何在屏幕上看到线程的两种行为的差异?

  public class ChocolateBoiler {    

        private boolean empty;
        private boolean boiled;
        private static ChocolateBoiler chocolateBoilerInstance;

        public ChocolateBoiler() {
            empty = true;
            boiled = false;
        }

        public static (synchronized) ChocolateBoiler getInstance() {
            if (chocolateBoilerInstance == null) {
                chocolateBoilerInstance = new ChocolateBoiler();
            }
            return chocolateBoilerInstance;
        }

        public void fill() {
            if (isEmpty()) {
                empty = false;
                boiled = false;
                // fill the boiler with a milk/chocolate mixture
            }
        }

        public void drain() {
            if (!isEmpty() && isBoiled()) {
                // drain the boiled milk and chocolate
                empty = true;
            }
        }

        public void boil() {
            if (!isEmpty() && !isBoiled()) {
                // bring the contents to a boil
                boiled = true;
            }
        }

        public boolean isEmpty() {
            return empty;
        }

        public boolean isBoiled() {
            return boiled;
        }

        public static void main(String[] args) {

            ChocolateBoiler boiler = ChocolateBoiler.getInstance();
            boiler.fill();
            boiler.boil();
            boiler.drain();
        }
 }

您的例子太复杂了。 我创建了另一个更简单的代码。 如果按原样运行,您将在控制台中看到0和1混合在一起的行,如下所示:

11111111111111111111000000000000111111111111111111
11111111111111111111110000000000001111111111111111

原因是两个线程同时在单例中修改了相同的实例变量“值”。

现在,将单词“ synchronized”添加到方法“ setValue”和“ printValue”中,然后再次运行。 您将看到,所有行仅由0或1组成。 他们不再混在一起。

00000000000000000000000000000000000000000000000000
11111111111111111111111111111111111111111111111111

原因是,在任何时候,只有一个线程会修改变量,因为“同步”会阻止从不同线程同时访问单例对象。

这是代码:

public class Main {

    public static class Singleton {

        private static Singleton instance = new Singleton();

        public static Singleton getInstance() {
            return instance;
        }

        private char[] value = new char[50];

        private Singleton() {
        }

        public void printValue() {
            for (int i = 0; i < value.length; i++) {
                System.out.print(value[i]);
            }
            System.out.println();
        }

        public void setValue(String newValue) {
            for (int i = 0; i < newValue.length() && i < value.length; i++) {
                value[i] = newValue.charAt(i);
                try {
                    Thread.sleep(1);
                } catch (InterruptedException e) {
                    // Ignore
                }
            }
        }

    }

    public static void main(String[] args) {
        final int MAX = 100000;

        Thread thread1 = new Thread() {
            @Override
            public void run() {
                for (int i = 0; i < MAX; i++) {
                    Singleton.getInstance().setValue("00000000000000000000000000000000000000000000000000");
                    yield();
                }
            }
        };

        Thread thread2 = new Thread() {
            @Override
            public void run() {
                for (int i = 0; i < MAX; i++) {
                    Singleton.getInstance().setValue("11111111111111111111111111111111111111111111111111");
                    yield();
                }
            }
        };

        Thread thread3 = new Thread() {
            @Override
            public void run() {
                for (int i = 0; i < MAX; i++) {
                    System.out.printf("%5d:   ", i);
                    Singleton.getInstance().printValue();
                    yield();
                }
            }
        };

        thread1.start();
        thread2.start();
        thread3.start();
    }

}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM