3、并发编程基础-ThreadLocal 和 单例多线程

1、TheadLocal

ThreadLocal概念:线程局部变量,是一种多线程间并发访问变量的解决方案。与其synchronized等加锁的方法不同,ThreadLocal完全不提供加锁,而使用空间换时间的手段,为每个线程提供变量的独立副本,以保证线程安全。

从性能上说,ThreadLocal不惧有绝对的优势,在并发很高的时候,加锁的性能会更好,但作为一套与锁完成无关的线程安全解决方案,在高并发量或者竞争激烈的场景,使用ThreadLocal可以在一定程度上减少锁竞争。

public class ConnThreadLocal {

    public static ThreadLocal<String> th = new ThreadLocal<String>();

    public void setTh(String value) {
        th.set(value);
    }

    public void getTh() {
        System.out.println(Thread.currentThread().getName() + ":" + this.th.get());
    }

    public static void main(String[] args) throws InterruptedException {
        final ConnThreadLocal ct = new ConnThreadLocal();
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                ct.setTh("张三");
                ct.getTh();
            }
        }, "t1");
        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(1000);
                    ct.getTh();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "t2");
        t1.start();
        t2.start();
    }
}

2、单例多线程

单例模式,最常见的就是饥饿模式和懒汉模式,前者是直接实例化对象,后者是方法调用时才进行对象实例化。

在多线程模式中,上面的2种模式都不一定是安全的。考虑到性能和线程安全的问题,我们一般选择静态内部类的模式,在性能提高的同时,又保证了线程的安全。

单例多线程:最安全解决方案是使用静态内部类 static inner class 的方法。

如下面的代码:

public class Singletion {

//static inner class 静态内部类
private static class InnerSingletion {
        private static Singletion single = new Singletion();
}

public static Singletion getInstance(){
        return InnerSingletion.single;
    }
}

还有一种模式就是 dubble check Instance 。对初始化对象做2次判断,如果不做2次判断,也有可能因为线程竞争导致线程不安全。

dubble check Instance 模式代码如下:

public class DubbleSingleton {

    private static DubbleSingleton ds;

    public  static DubbleSingleton getDs(){
        //第一次判断
        if(ds == null){
            try {
                //模拟初始化对象的准备时间...
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            synchronized (DubbleSingleton.class) {
                //第二次加锁判断
                if(ds == null){
                    ds = new DubbleSingleton();
                }
            }
        }
        return ds;
    }

    public static void main(String[] args) {
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println(DubbleSingleton.getDs().hashCode());
            }
        },"t1");
        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println(DubbleSingleton.getDs().hashCode());
            }
        },"t2");
        Thread t3 = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println(DubbleSingleton.getDs().hashCode());
            }
        },"t3");

        t1.start();
        t2.start();
        t3.start();
    }

}

猜你喜欢

转载自blog.csdn.net/sumlyl/article/details/80948017
今日推荐