JAVA 多线程(9):单例模式 与线程组

单例模式大家都知道,不用多说,就是只保持一个实例~

 

比如(饥饿模式/饿汉模式):

private static TestOne testOne = new TestOne();

    private TestOne() {
    }

    public static TestOne getInstance(){
        return testOne;
    }

 

延迟加载:

private static TestOne testOne = null;

    private TestOne() {
    }

    public static TestOne getInstance(){
        if(testOne==null){
            testOne = new TestOne();
        }
        return testOne;
    }

下面针对懒汉模式与多线程的实例。

如果是在多线程的情况下,就有可能出现错误,比如:

private static TestOne testOne = null;

    private TestOne() {
    }

    public static TestOne getInstance() {
        if (testOne == null) {
            try {
                Thread.sleep(5000);
                testOne = new TestOne();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        return testOne;
    }

    public static void main(String[] args) {
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                System.out.println(TestOne.getInstance().hashCode());
            }
        };

        Thread t = new Thread(runnable);
        Thread t2 = new Thread(runnable);
        t.start();
        t2.start();
    }

输出:

说明创建了2个对象实例。

 

那么就同步呗:synchronized

synchronized (TestOne.class) {
            if (testOne == null) {
                try {
                    Thread.sleep(5000);
                    testOne = new TestOne();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }

输出:

 

提高效率:

if (testOne == null) {
            try {
                Thread.sleep(5000);
                synchronized (TestOne.class) {
                    if (testOne == null) {
                        testOne = new TestOne();
                    }
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

输出:

 

 这样的话,就只是在创建实例的时候进行同步,并且在同步中判断,那能不能把第一层去掉,不能,原因在于,如果只是单纯创建实例可以,但是如果在创建实例之前有其他操作的话还是要加2层。

官方叫这种用法叫做DCL检查机制(双重检查锁)。

 

 还有其他的方式比如上面说的创建静态实例对象立即加载,或者静态内部类也可以(但是如果是序列化对象就不行),还有枚举。其实我觉得DCL 就挺好不是么~

 

 

关于线程组:

线程太多了,所以有了组,线程组用来统一管理多个线程,并且线程组是树形结构,线程组中还可以有线程组。

实例如下:

public static void main(String[] args){
        // 隐私的添加了导主线程中
        ThreadGroup threadGroup = new ThreadGroup("线程组");
        // 添加到线程组中
        Thread t = new Thread(threadGroup, new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName());
            }
        },"子线程");
        t.start();
        System.out.println(threadGroup.activeCount());
        System.out.println(threadGroup.getName());
    }

输出:

 

线程组拷贝:

ThreadGroup[] threadGroups = new ThreadGroup[Thread.currentThread().getThreadGroup().activeCount()];
        Thread.currentThread().getThreadGroup().enumerate(threadGroups);

 

posted @ 2019-05-08 19:15  李鹏飞ONLINE  阅读(143)  评论(0编辑  收藏  举报