日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

ThreadLocal与Synchronized的用法

發布時間:2024/7/23 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 ThreadLocal与Synchronized的用法 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

來源:http://blog.csdn.net/wl_ldy/article/details/5948779

一.ThreadLocal的用法

ThreadLocal的實現:

package com.sodao.lucene; import java.util.Random; public class ThreadLocalTest implements Runnable{ ThreadLocal<Studen> studenThreadLocal = new ThreadLocal<Studen>(); @Override public void run() { String currentThreadName = Thread.currentThread().getName(); System.out.println(currentThreadName + " is running..."); Random random = new Random(); int age = random.nextInt(100); System.out.println(currentThreadName + " is set age: " + age); Studen studen = getStudent(); //通過這個方法,為每個線程都獨立的new一個student對象,每個線程的的student對象都可以設置不同的值 studen.setAge(age); System.out.println(currentThreadName + " is first get age: " + studen.getAge()); try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println( currentThreadName + " is second get age: " + studen.getAge()); } private Studen getStudent() { Studen studen = studenThreadLocal.get(); if (null == studen) { studen = new Studen(); studenThreadLocal.set(studen); } return studen; } public static void main(String[] args) { ThreadLocalTest t = new ThreadLocalTest(); Thread t1 = new Thread(t,"Thread A"); Thread t2 = new Thread(t,"Thread B"); t1.start(); t2.start(); } } class Studen{ int age; public int getAge() { return age; } public void setAge(int age) { this.age = age; } }

Synchronized的實現:

package com.sodao.lucene; import java.util.Random; public class MultiThreadTest implements Runnable{ Studen studen = new Studen(); @Override public void run() { String currentThreadName = Thread.currentThread().getName(); System.out.println(currentThreadName + " is running ...."); //同步 synchronized (studen) { Random random = new Random(); int age = random.nextInt(100); studen.setAge(age); System.out.println(currentThreadName + " is set age: " + age); System.out.println(currentThreadName + "is first get age: " + studen.getAge() ); try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(currentThreadName + " is second get age: " + studen.getAge() ); } } public static void main(String[] args) { MultiThreadTest m = new MultiThreadTest(); Thread t1 = new Thread(m,"Thread A"); Thread t2 = new Thread(m,"Thread B"); t1.start(); t2.start(); } } class Student { int age; public int getAge() { return age; } public void setAge(int age) { this.age = age; } } 以上2中方法都實現的功能相同,但方法不一樣?

ThreadLocal使用場合主要解決多線程中數據數據因并發產生不一致問題。 ThreadLocal為每個線程的中并發訪問的數據提供一個副本 ,通過訪問副本來運行業務,這樣的結果是耗費了內存,單大大減少了線程同步所帶來性能消耗,也減少了線程并發控制的復雜度。?

ThreadLocal不能使用原子類型,只能使用Object類型。ThreadLocal的使用比synchronized要簡單得多。?

ThreadLocal和Synchonized都用于解決多線程并發訪問。但是ThreadLocal與synchronized有本質的區別。 synchronized是利用鎖的機制,使變量或代碼塊在某一時刻只能被一個線程訪問。而ThreadLocal為每一個線程都提供了變量的副本,使得每個線程在某一時間訪問到的并不是同一個對象,這樣就隔離了多個線程對數據的數據共享。 而Synchronized卻正好相反,它用于在多個線程間通信時能夠獲得數據共享。?

Synchronized用于線程間的數據共享,而ThreadLocal則用于線程間的數據隔離。 ?

當然ThreadLocal并不能替代synchronized,它們處理不同的問題域。Synchronized用于實現同步機制,比ThreadLocal更加復雜。?

ThreadLocal使用的一般步驟:?

1、在多線程的類(如ThreadDemo類)中,創建一個ThreadLocal對象threadXxx,用來保存線程間需要隔離處理的對象xxx。?
2、在ThreadDemo類中,創建一個獲取要隔離訪問的數據的方法getXxx(),在方法中判斷,若ThreadLocal對象為null時候,應該new()一個隔離訪問類型的對象,并強制轉換為要應用的類型。?
3、在ThreadDemo類的run()方法中,通過getXxx()方法獲取要操作的數據,這樣可以保證每個線程對應一個數據對象,在任何時刻都操作的是這個對象。


二.ThreadLocal的實現原理:
public class ThreadLocal { private Map values = Collections.synchronizedMap(new HashMap()); public Object get() { Thread curThread = Thread.currentThread(); Object o = values.get(curThread); if (o == null && !values.containsKey(curThread)) { o = initialValue(); values.put(curThread, o); } return o; } public void set(Object newValue) { values.put(Thread.currentThread(), newValue); } public Object initialValue() { return null; } } 由此可見,ThreadLocal通過一個Map來為每個線程都持有一個變量副本。這個map以當前線程為key。與synchronized相比,ThreadLocal是以空間換時間的策略來實現多線程程序。?

Synchronized還是ThreadLocal??
ThreadLocal以空間換取時間,提供了一種非常簡便的多線程實現方式。因為多個線程并發訪問無需進行等待,所以使用ThreadLocal會獲得更大的性能。雖然使用ThreadLocal會帶來更多的內存開銷,但這點開銷是微不足道的。因為保存在ThreadLocal中的對象,通常都是比較小的對象。另外使用ThreadLocal不能使用原子類型,只能使用Object類型。ThreadLocal的使用比synchronized要簡單得多。?
ThreadLocal和Synchonized都用于解決多線程并發訪問。但是ThreadLocal與synchronized有本質的區別。synchronized是利用鎖的機制,使變量或代碼塊在某一時該只能被一個線程訪問。而ThreadLocal為每一個線程都提供了變量的副本,使得每個線程在某一時間訪問到的并不是同一個對象,這樣就隔離了多個線程對數據的數據共享。而Synchronized卻正好相反,它用于在多個線程間通信時能夠獲得數據共享。?
Synchronized用于線程間的數據共享,而ThreadLocal則用于線程間的數據隔離。?
當然ThreadLocal并不能替代synchronized,它們處理不同的問題域。Synchronized用于實現同步機制,比ThreadLocal更加復雜。


2012-05-23新增 每一個線程都維護一個本地對象的副本,類圖如:


ThreadLocal 只是提供當前線程(Thread.currentThread( ) )對副本(ThreadLocal.ThreadLocalMap)的操作。 部分源代碼 public T get() {Thread t = Thread.currentThread();ThreadLocalMap map = getMap(t);if (map != null) {ThreadLocalMap.Entry e = map.getEntry(this);if (e != null)return (T)e.value;}return setInitialValue();} ThreadLocalMap getMap(Thread t) {return t.threadLocals;}

疑問:ThreadLocal每種類型的對象只能存儲一個? 應該是的,因為 map 的key 值是 ThreadLocal對象。下面是 ThreadLocal 部分源代碼: public void set(T value) {Thread t = Thread.currentThread();ThreadLocalMap map = getMap(t);if (map != null)map.set(this, value);elsecreateMap(t, value);}

總結

以上是生活随笔為你收集整理的ThreadLocal与Synchronized的用法的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。