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

xiaoxiao2021-02-28  132

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(); } }
转载请注明原文地址: https://www.6miu.com/read-2600291.html

最新回复(0)