1、对于多线程资源共享的问题,同步机制采用了“以时间换空间”的方式,而ThreadLocal采用了“以空间换时间”的方式。前者仅提供一份变量,让不同的线程排队访问,而后者为每一个线程都提供了一份变量,因此可以同时访问而互不影响。
2、ThreadLocal使用场合主要解决多线程中数据因并发产生不一致问题。ThreadLocal为每个线程的中并发访问的数据提供一个副本,通过访问副本来运行业务,这样的结果是耗费了内存,单大大减少了线程同步所带来性能消耗,也减少了线程并发控制的复杂度。
3、ThreadLocal不能使用基本数据类型,只能使用Object类型。ThreadLocal的使用比synchronized要简单得多。
ThreadLocal和Synchonized都用于解决多线程并发访问。但是ThreadLocal与synchronized有本质的区别。
synchronized是利用锁的机制,使变量或代码块在某一时该只能被一个线程访问。
而ThreadLocal为每一个线程都提供了变量的副本,使得每个线程在某一时间访问到的并不是同一个对象,这样就隔离了多个线程对数据的数据共享。而Synchronized却正好相反,它用于在多个线程间通信时能够获得数据共享。
4、Synchronized用于线程间的数据共享,而ThreadLocal则用于线程间的数据隔离。
示例1:
//线程局部变量 protected static ThreadLocal<Connection> threadLocalCon = new ThreadLocal<Connection>(); /* * 获取数据库连接 */ public static Connection getCon() { Connection con = threadLocalCon.get(); System.out.println("当前线程名称="+Thread.currentThread().getName()+",con="+con); try { if (con == null || con.isClosed()) { Class.forName(driver); con = DriverManager.getConnection(url, username, password); threadLocalCon.set(con); System.out.println("当前线程="+Thread.currentThread().getName()+",新建连接"+con); System.out.println("当前线程="+Thread.currentThread().getName()+",threadLocalCon.get()="+threadLocalCon.get()); try { System.out.println("当前线程="+Thread.currentThread().getName()+",开始休眠"); Thread.currentThread().sleep(10000); System.out.println("当前线程="+Thread.currentThread().getName()+",结束休眠"); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } return con; }
启动2个线程先后发出请求:
小结:
1、线程局部变量threadLocalCon为每一个线程分别提供一个该变量的副本,所以,每个线程第一次访问该变量时,通过get()取得的值都是null。
2、客户端的每一次请求,服务端都会新建一个线程为其服务,一次请求结束,相对应的线程也随之随之结束。
示例2、
在getCon()方法中加上synchronized关键字,再次执行(两次请求之间发起时间间隔短于10秒),看效果:
小结:
1、synchronized是利用锁的机制,使变量或代码块在某一时该只能被一个线程访问,第一个线程在getCon()执行完成之前,第二个线程只能等待。