Java多線程學習與總結(一)

來源:互聯網
上載者:User

標籤:

前段時間做了一個利用多線程解決查詢大資料的功能,之前是用.NET寫的,因工作需要,開始瞭解學習Java。

於是,開始去瞭解Java裡面多線程是怎麼個寫法,線程同步是怎麼進行的?

之前.NET裡面寫多線程程式,也是一知半解,並沒有用到很多線程特性,只是很簡單的Thread.start();

lock(obj)

{

}

來保證多個線程資料同步,甚至多個線程判斷執行完畢否,還是採用 主線程

while(計數器!=0){

Thread.Sleep(100);

}

期間,線程同步問題相當讓我頭痛,對象集合以引用的方式在不同方法中,不同線程中的操作,更是讓我心驚膽戰。

最後,成功解決了大資料分表查詢功能。(日後考慮貼出來,讓大夥指教下)。

根據.NET版本的的代碼,現在打算轉換為Java版本的代碼,第一直觀的映像就是Java開發動不動就extends繼承。

對匿名寫法支援不是很好,文法確實不優雅,比較臃腫和繁瑣。(8支援 拉姆達運算式了)

 

回到 多線程,首先我得知道是怎麼調用的,貼一段代碼(代碼就找了網上的):

/**
* 使用繼承java.lang.Thread類的方式建立一個線程
*
* @author DreamSea 2011-12-29 20:17:06
*/
public class ThreadTest extends Thread {

    /**
     * 重寫(Override)run()方法 JVM會自動調用該方法
     */
    public void run() {
        System.out.println("I‘m running!");
    }
}

第二種,實現介面。

/**
* 通過實現Runnable介面建立一個線程
* @author DreamSea
*/
public class ThreadTest2 implements Runnable {
    public void run() {
            System.out.println("I‘m running!");
    }
}

 

需要注意下,上面ThreadTest2 類只是簡單的實現了一個介面的普通類。

如果你 這樣使用 new ThreadTest2().run();

根本不會在單獨線程中跑,不要被它 Thread名稱所迷惑,它和線程一毛關係都沒有,只是一個實現普通介面的類而已。

而 ThreadTest不一樣的,它繼承了 Thread類,它的基類已經實現了相關線程處理方法。

new ThreadTest().start() 會以多線程的方式執行。

那麼實現介面的類,如果作為多線程方式執行呢?如下:

ThreadTest2 tt = new ThreadTest2();
Thread t = new Thread(tt);
t.start();
 
好,上面瞭解了怎麼使用。
那麼多線程是個什麼東西呢?和單線程有什麼區別嗎?
比如我們看電影,它是電腦不斷重繪畫面,讓我們看到一種即時動畫的效果。
而且,我們可以一邊看電影,一邊開啟聊天軟體聊天。感覺這些軟體都是同步進行的。
這裡我的理解是這樣的,
每個程式佔一條流水線,不同程式的指令可以同時執行。
CPU每次只能一條條的執行指令,機器周期內最多能執行 N條指令。
多核電腦機器周期內可以處理的指令會增加很多。
如果不是多線程的話,只會在CPU某核心上面一條條指令的運行。
而實際上,現在多核cpu利用率並不充分,也就是說,機器周期內可以處理的CPU指令其實可以增加很多。
單線程執行100條指令,只能一條條的執行,假設每個周期能夠處理 5條指令,4核心。
100/5=20個周期時間。
如果用多執行緒,除去資源競爭等情況,周期時間內可以處理 4*5=20條指令。
100/20=5個周期時間。
這就是多核CPU用多線程程式的好處了,至於單核CPU,多線程沒有任何協助。
 
這裡找了一線程狀態圖,感謝(http://www.cnblogs.com/DreamSea/archive/2012/01/11/JavaThread.html)
 

 
 

可以看到,線程的start()並不一定代表已經執行多線程了,start()之後,狀態為 runnable(就緒狀態),

然後在被 JVM調用之後,線程才會被運行。

運行過程中,可以通過 sleep(),join(),yiled(),blocked方法改變線程運行狀態,又可以讓線程由運行狀態,改變為“暫停”狀態,

然後通過相關方法,改變暫停狀態為 就緒狀態,等待被JVM調用繼續執行。

 

這裡主要瞭解了 object.wait()方法,和Thread.Sleep()方法。

都是將線程狀態改變為暫停狀態,有什麼區別呢?

首先明確 給出, sleep方法 是 計時器來決定是否回到就緒狀態以待執行的。

wairt方法 需要給接受 nofity()通知才可以繼續執行。

 

要深入瞭解這些,必須要瞭解線程同步的含義了,才能明白為什麼要用這些方法。

線程有可能和其他線程共用一些資源,比如,記憶體,檔案,資料庫等。

當多個線程同時讀寫同一份共用資源的時候,可能會引起衝突。這時候,我們需要引入線程“同步”機制,即各位線程之間要有個先來後到,不能一窩蜂擠上去搶作一團。

線程同步的真實意思和字面意思恰好相反。線程同步的真實意思,其實是“排隊”:幾個線程之間要排隊,一個一個對共用資源進行操作,而不是同時進行操作。

 

線程同步的方法

(1)wait():使一個線程處於等待狀態,並且釋放所持有的對象的lock。

(2)sleep():使一個正在啟動並執行線程處於睡眠狀態,是一個靜態方法,調用此方法要捕捉

InterruptedException異常。

(3)notify():喚醒一個處於等待狀態的線程,注意的是在調用此方法的時候,並不能確切的

喚醒某一個等待狀態的線程,而是由JVM確定喚醒哪個線程,而且不是按優先順序。

(4)notityAll ():喚醒所有處入等待狀態的線程,注意並不是給所有喚醒線程一個對象的鎖,

而是讓它們競爭

 

object.wait()方法,和Thread.Sleep()

注意,這些方法都是針對線程同步的。

 

  1. private void mainLoop() {  
  2. while (true) {  
  3. ....  
  4. synchronized(queue) {  
  5. .....  
  6. if (!taskFired) // Task hasn‘t yet fired; wait  
  7. queue.wait(executionTime - currentTime);  
  8. }  
  9. }
 
  
  1. private void sched(TimerTask task, long time, long period) { 
  2. synchronized(queue) { 
  3. ... 
  4. queue.add(task); 
  5. }

 

如上,如果調用 wait()方法,實際就是說,當前這個線程不再阻止其他線程繼續執行了,因為在 synchronized代碼塊中,必須代碼塊裡面的方法全部執行完畢,才能執行下一個線程。

wait恰恰是說,好了,我還需要某些條件,你們繼續執行,你們執行好了通知我就好了。主要是讓出執行的權利,退出阻塞。(wait 是 object對象的基本方法,也就是作為對象鎖的對象,對象鎖稍後解釋。)

Sleep()方法,會一直等待在那裡,阻塞其他線程執行。

 

好了知道這個區別很重要,下面再回頭來解釋下 synchronized中的對象鎖。

 

1、對於同步的方法或者代碼塊來說,必須獲得對象鎖才能夠進入同步方法或者代碼塊進行操作;
2、如果採用method層級的同步,則對象鎖即為method所在的對象,如果是靜態方法,對象鎖即指method所在的
Class對象(唯一);
3、對於代碼塊,對象鎖即指synchronized(abc)中的abc;

 

那麼我們看看這些 鎖對象:

String lock=new String(“”);

 

Threada{

  private String lock;

PUBLIC (String lock){lock=lock;}

 

run(){

synchronized(lock){

 

}

}

}

 

main(){

String lockObj=new String(“lock”);

new Threada(lockObj).start();

new Threada(lockObj).start();

new Threada(lockObj).start();

}

 

在java 中,lockObj是值引用,而且這裡是 主線程中的對象,所以各個 線程實際上鎖對象是同一個,是main方法裡面的 lockObj對象。

 

static synchronized run(){

 

}

這裡 synchronized 引用的是這個方法的對象本身,因為設定了 static,所以這裡針對的不是 該類的對象,而是該類本身。

 

好了,下班了,基本概念釐清了。

Java多線程學習與總結(一)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.