在過去一臺電腦只有單個CPU,而且在同一時間只能執行單個程序。後來出現的"多任務"意味着電腦在能夠同時執行多個程序(AKA任務或者進程)。雖然那並非真正意義上的"同時"。多個程序之間共享僅有的一個CPU。操做系統會切換正在運行着的進程,在每次切換以前都會運行它們其中一個一小會兒。java
多任務模型的產生給軟件開發者帶來了新的挑戰。程序再也不假設爲能夠一直佔用CPU時間,也再也不佔有全部的內存或者任何其餘的計算機資源。做爲操做系統中的一個"良好公民",程序應當釋放全部那些它再也不使用的資源,這樣其餘的程序就可使用這些被釋放的資源。算法
後來又出現了多線程模型,這意味着你能夠在同一個進程中運行多個線程。線程的執行能夠看做是CPU正在執行線程所在的程序。當你在同一個進程中運行了多個線程的時候,就像在同一個程序中有多個CPU正在運行同樣。數據庫
多線程能夠極大地提升某些類型程序地性能。而後,多線程要比多任務複雜得多。在同一個進程中能夠運行多個線程,所以這些線程能夠同時讀寫相同內存塊。這樣會出現那些在單線程程序中不會出現地問題。並且其中某些問題並不會在單CPU機器中出現,由於在單CPU機器中兩個線程歷來就沒有真正"同時"執行過。可是如今地計算機,大可能是多核CPU,甚至也多是多個CPU。這意味着不一樣的線程能夠同時在不一樣的核或者CPU上同時執行。編程
若是一個線程在讀一塊內存區域的同時另外一個線程在想這塊內存寫入數據,那麼第一個線程在執行完讀操做以後拿到的是什麼值呢?是舊的值?仍是第二個線程寫入的新值呢?或者是兩者混合以後的一個值?再或者,若是兩個線程同時向同一個塊內存區域寫入數據,那麼在它們的操做執行完以後,那塊內存中的值是多少呢?是第一個線程寫入的值?仍是第二個線程寫入的值?或者是兩個寫入值的混合值?多線程
若是沒有合適的預防措施那麼上面任何一種結果都是可能的。這種行爲甚至沒法預測。出現的結果時時刻刻都不相同。所以一個開發人員必需要知道若是採起正確的預防措施 - 所以要學習若是控制線程對共享資源的訪問,好比內存,文件,數據庫等。這就是Java併發教程解決的問題之一。架構
Java中的多線程和併發
Java是第一個使開發人員很容易上手多線程的語言。Java在一開始就支持多線程。所以,Java開發者常常會遇到上面描述的問題。這就是我爲何寫這篇關於Java併發的教程。對於而言能夠做爲筆記,同時也可使Java開發同行從中獲益。併發
本教程主要關注於Java中的多線程,可是其中有些問題在多線程中出現的問題也一樣會在多任務和分佈式系統中出現。這篇教程中一樣也會出現多任務和分佈式系統的參考。所以我用了"併發"這個詞而不是"多線程"。框架
2015年的Java併發和之後的
自從第一批Java併發數據問世以後,關於併發架構和設計已經發生了不少的變化,即便是在Java 5中併發工具發佈之後也是如此。異步
現在,又出現了相似Vert.x和Play/Akkay以及Qbit等異步"無共享"的平臺和API。這些平臺使用不一樣於標準Java/JEE中的線程併發模型,共享內存和鎖。還出版了新的非阻塞的併發算法,並且相似LMax Disrupter這種非阻塞工具也已經加入到了咱們的開發工具中。新的函數編程並行模式也隨着Fork和Join框架引入到了Java 7中,以及Java 8中的集合流API。分佈式
隨着新特性的不斷出現,也到了我該更新這個Java併發教程了。所以,本教程又會在更新中了。我會在合適的寫新的教程併發布它們。