一、ThreadLocal
使用wait/notify方式实现的线程安全,性能将受到很大影响。解决方案是用空间换时间,不用锁也能实现线程安全。
来看一个小例子,在线程内的set、get就是threadLocal
1 public class ConnThreadLocal { 2 3 public static ThreadLocal<String> th = new ThreadLocal<String>(); 4 5 public void setTh(String value){ 6 th.set(value); 7 } 8 public void getTh(){ 9 System.out.println(Thread.currentThread().getName() + ":" + this.th.get()); 10 } 11 12 public static void main(String[] args) throws InterruptedException { 13 14 final ConnThreadLocal ct = new ConnThreadLocal(); 15 Thread t1 = new Thread(new Runnable() { 16 @Override 17 public void run() { 18 ct.setTh("张三"); 19 ct.getTh(); 20 } 21 }, "t1"); 22 23 Thread t2 = new Thread(new Runnable() { 24 @Override 25 public void run() { 26 try { 27 Thread.sleep(1000); 28 ct.getTh(); 29 } catch (InterruptedException e) { 30 e.printStackTrace(); 31 } 32 } 33 }, "t2"); 34 35 t1.start(); 36 t2.start(); 37 } 38 39 }
二、单例和多线程
单例常见的有饥饿模式和懒汉模式,但是这两个模式在多线程情况下是不行的。在多线程中考虑到新能和线程安全的问题一般考虑double check instance 和 static inner class这两种方式实现单例模式。
static inner class方式:
1 public class InnerSingleton{ 2 private static class Singleton{ 3 private static Singleton single = new Singleton(); 4 } 5 public Singleton getInstance(){ 6 return Singleton.single; 7 } 8 }
double check instance 方式:
1 public class DubbleSingleton { 2 3 private static DubbleSingleton ds; 4 5 public static DubbleSingleton getDs(){ 6 if(ds == null){ 7 try { 8 //模拟初始化对象的准备时间... 9 Thread.sleep(3000); 10 } catch (InterruptedException e) { 11 e.printStackTrace(); 12 } 13 synchronized (DubbleSingleton.class) { 14 if(ds == null){ 15 ds = new DubbleSingleton(); 16 } 17 } 18 } 19 return ds; 20 } 21 22 public static void main(String[] args) { 23 Thread t1 = new Thread(new Runnable() { 24 @Override 25 public void run() { 26 System.out.println(DubbleSingleton.getDs().hashCode()); 27 } 28 },"t1"); 29 Thread t2 = new Thread(new Runnable() { 30 @Override 31 public void run() { 32 System.out.println(DubbleSingleton.getDs().hashCode()); 33 } 34 },"t2"); 35 Thread t3 = new Thread(new Runnable() { 36 @Override 37 public void run() { 38 System.out.println(DubbleSingleton.getDs().hashCode()); 39 } 40 },"t3"); 41 42 t1.start(); 43 t2.start(); 44 t3.start(); 45 } 46 47 }