Java线程概念
實現線程最簡單的做法是從java.lang.Thread繼承,然后覆蓋其run()方法。必須調用start()方法來啟動線程。對于Thread對象,雖然在用戶程序看來可能沒有對它的引用,但這并不會使它成為垃圾回收器要回收的對象(其他的對象若沒有引用會被回收),因為Thread對象需要注冊自己(start函數作用),所以實際上在某個地方存在對它的引用垃圾回收器只有在線程離開了run()并且死亡之后才會把它清理掉。
yield()方法可以在run()中用來暗示作出讓步,但機制并不保證它一定會被采納。 sleep()使線程休眠給定的毫秒數時間。使用時必須放在try塊中,因為sleep()可能會在休眠期間被中斷(比如對此線程調用interrupt()函數)。 setPriority()和 getPriority()用來設置 或者 取得線程的優先權。注意優先級低的線程僅僅是執行的頻率較低,不代表不會被執行,因此優先權不會導致死鎖。 可以再調用start()啟動線程前調用setDaemon(true)把它設置為后臺線程。如果程序里面沒有非后臺線程,那么程序會立即終止,即使還有后臺線程在運行。后臺線程創建的任何線程都會自動設置為后臺線程。可以通過調用isDaemon()來判斷某線程是否為后臺線程。 有線程A,B。如果在 線程A 內部調用了B.join() ?,那么 線程A 會被掛起,直至目標線程B 結束才恢復。如果join()帶上了超時參數,就會在超時后返回。join()函數同樣可以被interrupt()函數中斷。 也可以通過實現Runnable接口來達到目的。實現Runnable接口只需要實現run()方法。但對象具有Runnable接口,也僅僅只是表面他有run()方法而已,本身并不帶有任何和線程有關的特性。因此要從Runnable對象產生線程,必須建立一個單獨的Thread對象,并把實現的Runnable對象作為參數傳遞,并調用Thread對象的start()方法。還必須通過Thread.currentThread() 方法才能明確得到對此線程的引用。 Java提供了關鍵字synchronized來解決共享資源競爭。要控制對共享資源的訪問,先把它包裝為一個對象,然后把所有要訪問這個資源的方法標記為synchronized。一旦某個線程處于一個標記為synchronized的方法中,那么在這個線程從該方法返回之前,其他所有要調用類中標記為synchronized方法的線程都會被阻塞。每個對象都含有單一的鎖,作為對象自身的一部分。當在對象上調用其任意的synchronized方法的時候,此對象都會被加鎖,同一個對象的所有synchronized方法共享同一個鎖,這能防止資源被多個線程同時訪問。但同時,一個線程可以多次獲得對象的鎖,這允許在一個synchronized方法內調用另一個synchronized方法,顯然只有首先獲得了鎖的線程才能允許繼續獲取多個鎖。JVM會負責跟蹤對象被加鎖的次數。對于每個類,也有一個鎖,作為類的一部分,這樣synchronized static 方法可以在類的范圍內防止對static數據的并發訪問。 線程之間的協作 當一個線程在方法里調用wait()時,線程的執行將被掛起。如果接受毫秒數作為參數,表示在此期間暫停。不同的是wait()期間對象的鎖是釋放的,這意味著可以調用線程對象中的其他同步控制方法,而sleep()期間鎖沒有釋放。可以通過notify()、notifyAll()、或者時間到期,從wait()恢復。如果不接受參數,wait()將無限等待下去,知道線程收到notify()、notifyAll()消息。 wait()、notifyAll()、notify()是基類Object的一部分,因此只能在同步控制方法或者同步控制塊里調用這些函數,而不是像sleep()那樣屬于Thread的一部分。 synchronized(對象){
 ????????臨界區代碼
????}?
那么對于public synchronized void add(int num)這種情況,意味著什么呢?其實這種情況,鎖就是這個方法所在的對象。同理,如果方法是public??static synchronized void add(int num),那么鎖就是這個方法所在的class。
轉載于:https://www.cnblogs.com/husterchenji/archive/2012/11/30/2796201.html
總結
                            
                        - 上一篇: 正睿2019省选附加赛 Day10 (这
 - 下一篇: centOS安装Ftp