《Java併發程式設計的藝術》第4章 Java併發程式設計基礎
Java誕生時就選擇了內建對多執行緒的支援
作業系統執行一個程式時,會為其建立一個程序。 執行緒是作業系統排程的最小單元,都有各自的計數器、堆疊、區域性變數。能訪問共享的記憶體變數。CPU在他們上高速切換,讓人感覺在同步執行。
執行緒會被分到若干時間片,時間片用完了就會發生執行緒排程。 設定優先順序時,對頻繁休眠和IO的執行緒設定高優先順序,需要大量計算佔用CPU的設定低優先順序。
作業系統可以完全不理會Java執行緒的優先順序設定。
4.1.5 Daemon執行緒 是一種支援型執行緒,用作程式的後臺排程和支援工作 需要在啟動執行緒之前設定
初始化執行緒在堆記憶體中等待著執行。
4.2.3 理解執行緒 一直在sleep的執行緒,中斷後interrupt標誌為false(丟擲InterruptException前,VM會把執行緒的標誌位被清除了) 一直在執行的執行緒,中斷後interrupt標誌為true
4.2.4 過期的suspend(),resume(),stop() suspend帶著鎖進入睡眠,容易引發死鎖問題,同樣,stop在終結一個執行緒時,不保證執行緒資源正常釋放。
4.2.5 安全地終止執行緒 interrupt和cancel,通過標識位的方式使終結前釋放資源
4.3.1 volatile和synchronized volatile確保可見性,某執行緒對欄位改變時,其他執行緒能感知變化。 synchronized使得方法或同步塊同一時間內只有一個執行緒操作
執行的執行緒必須先獲取物件的監視器才能進入同步塊或同步方法,獲取失敗,執行緒狀態變為BLOCKED。 notify通知在物件上等待的執行緒,從wait上返回。返回的前提是新執行緒獲得了物件的鎖(老執行緒釋放鎖) wait:得到其他執行緒的通知或被中斷才會返回,會釋放物件的鎖
4.3.3 等待/通知的經典範式 等待: 獲取物件鎖 是否符合條件 執行邏輯
通知: 獲取物件鎖 改變條件 通知所有等待在物件上的執行緒
4.3.4 管道輸入/輸出流 與用於執行緒間的資料傳輸,傳輸媒介是記憶體 輸入輸出流要connect起來,先write再print。
4.3.5 thread.join方法 當前執行緒A呼叫該方法,等待Thread執行緒結束後返回。
4.4.2 一個簡單的資料庫連線池示例
public class ConnectionDriver{ static class ConnectionHandler implements InvocationHandler{ public Object invoke(Object proxy,Method method,Object[] args) throws Throwable{ if(method.getName().equals("commit")){ TimeUnit.MILLISECONDS.sleep(100); } return null; } public static final Connection createConnection(){ return (Connection)Proxy.newProxyInstance(ConnectionDriver.class.getClassLoad new Class<>[]{Connection.class},new ConnectionHandler()); } }
4.4.3 執行緒池技術及其示例 執行緒池的本質就是使用了一個執行緒安全的工作佇列連線工作者執行緒和客戶端執行緒,客戶端執行緒將任務放入工作佇列後便返回,而工作者執行緒則不斷地從工作佇列上取出工作並執行。當工作佇列為空時,所有的工作者執行緒均等待在工作佇列上,當有客戶端提交了一個任務之後會通知任意一個工作者執行緒,隨著大量的任務被提交,更多的工作者執行緒會被喚醒。
SimpleHttpServer建立與客戶端連線後,不會處理客戶端的請求,而是將其包裝成HttpRequstHandler並交由執行緒池處理。