摘要:本人郵箱歡迎轉載轉載請注明網址代碼已經全部托管有需要的同學自行下載引言之前我們講到都是多線程共享數據那么有沒有某一個共享的變量在這變量里面每個線程都能擁有自己的屬性呢比如說去旅店開房休息那么這個旅店就是一個共享的數據但是每個人開的房間是不一
引言本人郵箱:
歡迎轉載,轉載請注明網址 http://blog.csdn.net/tianshi_kco
github: https://github.com/kco1989/kco
代碼已經全部托管github有需要的同學自行下載
之前我們講到都是多線程共享數據.那么有沒有某一個共享的變量,在這變量里面,每個線程都能擁有自己的屬性呢?比如說,去旅店開房休息.那么這個旅店就是一個共享的數據,但是每個人開的房間是不一樣的.這個要怎么做呢?這里我先試著寫一些
例子1讓我們編寫一個程序,主線程開啟十個子線程,然后每個子線程都做1~100的累加,都是共享同一個List
public class TestMain { public static class CalcRunnable implements Runnable{ Listlist ; int index; public CalcRunnable(List list, int index) { this.list = list; this.index = index; } @Override public void run() { for (int i = 1; i <= 100; i++){ list.set(index, list.get(index) + i); try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } } } } public static void main(String[] args) { List list = new ArrayList<>(); List threads = new ArrayList<>(); for (int i = 0; i < 10; i ++){ list.add(0); threads.add(new Thread(new CalcRunnable(list,i))); } for (Thread thread : threads){ thread.start(); } try { Thread.sleep(1500); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(list); } }
輸出結果為
[5050, 5050, 5050, 5050, 5050, 5050, 5050, 5050, 5050, 5050]
例子2這里每個線程都共享了list,但是也沒有使用關鍵字synchronized進行同步,為什么結果還是正確的呢?原因很簡單,那就是每個線程都使用固定的索引進行計算,互不干擾.所以結果不會受其他線程影響的.
現在把上面的例子中的List
public class TestMain1 { public static class CalcRunnable implements Runnable{ Mapmap; public CalcRunnable(Map map) { this.map = map; } @Override public void run() { Thread self = Thread.currentThread(); for (int i = 1; i <= 100; i++){ map.put(self, map.get(self) + i); try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } } } } public static void main(String[] args) { Map map = new HashMap<>(); List threads = new ArrayList<>(); for (int i = 0; i < 10; i ++){ Thread thread = new Thread(new CalcRunnable(map)); map.put(thread,0); threads.add(thread); } for (Thread thread : threads){ thread.start(); } try { Thread.sleep(1500); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(map); } }
運行結果
{Thread[Thread-1,5,]=5050, Thread[Thread-3,5,]=5050, Thread[Thread-6,5,]=5050, Thread[Thread-0,5,]=5050, Thread[Thread-8,5,]=5050, Thread[Thread-5,5,]=5050, Thread[Thread-7,5,]=5050, Thread[Thread-2,5,]=5050, Thread[Thread-4,5,]=5050, Thread[Thread-9,5,]=5050}
例子3結果也是完全正確,道理跟上面的例子一樣,每個線程雖然共用同一個數據map,但實際上每個線程都是用map中特定的那個元素
其實用map還有一種更簡單的方式,那就是今天要講的ThreadLocal,不廢話,看例子
public class TestMain3 { public static class CalcRunnable implements Runnable{ ThreadLocalthreadLocal; public CalcRunnable(ThreadLocal threadLocal) { this.threadLocal = threadLocal; } @Override public void run() { threadLocal.set(0);//設置默認值 for (int i = 1; i <= 100; i++){ threadLocal.set(threadLocal.get() + i); try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(Thread.currentThread().getName() + " 的計算結果為: " + threadLocal.get()); } } public static void main(String[] args) { ThreadLocal threadLocal = new ThreadLocal<>(); List threads = new ArrayList<>(); for (int i = 0; i < 10; i ++){ Thread thread = new Thread(new CalcRunnable(threadLocal)); threads.add(thread); } for (Thread thread : threads){ thread.start(); } } }
運行結果
Thread-0 的計算結果為: 5050 Thread-5 的計算結果為: 5050 Thread-1 的計算結果為: 5050 Thread-4 的計算結果為: 5050 Thread-7 的計算結果為: 5050 Thread-6 的計算結果為: 5050 Thread-3 的計算結果為: 5050 Thread-2 的計算結果為: 5050 Thread-8 的計算結果為: 5050 Thread-9 的計算結果為: 5050
總結原理,其實就是跟例子2的Map
,在ThreadLocal中實現了一個ThreadLocalMap內部類,然后在調用ThreadLocal.get和ThreadLocal.set的時候,其實要獲取當前線程去做相應的操作.
如果以后大家想讓多線程共享一個變量,但又不想互相影響的時候,那么首選ThreadLocal.因為對比上面三個例子,發現使用ThreadLocal是最簡單的,而且不容易出錯的.比如在web開發中,可以在多線程中存放session,或者數據庫連接池的時候,也可以使用ThreadLocal在存放數據庫連接.
打賞如果覺得我的文章寫的還過得去的話,有錢就捧個錢場,沒錢給我捧個人場(幫我點贊或推薦一下)
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/67042.html
摘要:前言本篇主要講解如何去優化鎖機制或者克服多線程因為鎖可導致性能下降的問題線程變量有這樣一個場景,前面是一大桶水,個人去喝水,為了保證線程安全,我們要在杯子上加鎖導致大家輪著排隊喝水,因為加了鎖的杯子是同步的,只能有一個人拿著這個唯一的杯子喝 前言 本篇主要講解如何去優化鎖機制或者克服多線程因為鎖可導致性能下降的問題 ThreadLocal線程變量 有這樣一個場景,前面是一大桶水,10個...
摘要:注意,和都是隨機選擇一個線程,解除其阻塞狀態,可能會造成死鎖。生產者線程向隊列插入元素,消費者線程從隊列取出元素。當添加時隊列已滿或取出時隊列為空,阻塞隊列導致線程阻塞。里面有個小技巧,一個線程搜索完畢時向阻塞隊列填充,讓所有線程能停下來。 多線程對共享數據的讀寫涉及到同步問題,鎖和條件是線程同步的強大工具。鎖用來保護代碼片段(臨界區),任何時刻只能有一個線程執行被保護的代碼。條件對象...
摘要:下面是線程相關的熱門面試題,你可以用它來好好準備面試。線程安全問題都是由全局變量及靜態變量引起的。持有自旋鎖的線程在之前應該釋放自旋鎖以便其它線程可以獲得自旋鎖。 最近看到網上流傳著,各種面試經驗及面試題,往往都是一大堆技術題目貼上去,而沒有答案。 不管你是新程序員還是老手,你一定在面試中遇到過有關線程的問題。Java語言一個重要的特點就是內置了對并發的支持,讓Java大受企業和程序員...
摘要:并沒有提供語言級的線程局部變量,而是在類庫里提供了線程局部變量的功能,也就是這次的主角類。 Yuicon 轉載請注明原創出處,謝謝! 序 在多線程環境下,訪問非線程安全的變量時必須進行線程同步,例如使用synchronized方式訪問HashMap實例。但是同步訪問會降低并發性,影響系統性能。這時候就可以用空間換時間,如果我們給每個線程都分配一個獨立的變量,就可以用非同步的方式使用非...
摘要:方法,刪除當前線程綁定的這個副本數字,這個值是的值,普通的是使用鏈表來處理沖突的,但是是使用線性探測法來處理沖突的,就是每次增加的步長,根據參考資料所說,選擇這個數字是為了讓沖突概率最小。 showImg(https://segmentfault.com/img/remote/1460000019828633); 老套路,先列舉下關于ThreadLocal常見的疑問,希望可以通過這篇學...
閱讀 1295·2021-11-23 09:51
閱讀 3399·2021-09-06 15:00
閱讀 987·2021-08-16 10:57
閱讀 1371·2019-08-30 12:46
閱讀 933·2019-08-29 12:22
閱讀 1604·2019-08-29 11:07
閱讀 3148·2019-08-26 11:23
閱讀 2980·2019-08-23 15:14