zoukankan      html  css  js  c++  java
  • 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);
    成灰之前,抓紧时间做点事!!
  • 相关阅读:
    常用词汇短语
    Java中的数据结构
    Java中的设计模式
    .NET中的编译、程序调用
    常用口语
    0. Angular框架原理
    茶叶
    NPOI自定义单元格背景颜色
    ASP.NET MVC添加Action就找不到
    navicat for mysql 导入SQL Server显示中文乱码解决办法
  • 原文地址:https://www.cnblogs.com/jony-it/p/10833868.html
Copyright © 2011-2022 走看看