J2SE快速進階——Java多線程機制

來源:互聯網
上載者:User

標籤:

        

       學習Java中的線程時,自然而然地聯想到之前學過的作業系統中處理器那一塊的知識。

       定義

       文章開頭,先大概說一下程式、進程和線程的概念及其之間的關係。

       程式:程式就是一段靜態代碼,或者一個可執行程式。

       進程:進程是程式的一次動態執行的過程,它對應著從代碼載入、運行到結束的一次動態執行過程。

       線程:比進程更小的執行單位,一個進程在執行過程中,可以產生多個線程,也就是多個分支。它是程式執行流的最小單位。

       來看一個小程式:

public class Test {public static void main(String[] args) {fun1();}public static void fun1(){System.out.println(fun2()+fun3());}public static String fun2(){return "Hello ";}public static String fun3(){return "World!";}}

          它的執行順序如下,在main方法中,從①執行到⑥是一條線,並沒有分支,這就是一個線程。

         


    

        線程的實現

        當JVM執行到main方法時,就會啟動一個線程,叫做主線程。如果main方法中還建立了其他線程,那麼JVM就會在主線程和其他線程之間輪流切換,保證每個線程都有機會使用CPU資源。

       Java中的線程是通過java.lang.Thread類來實現的,每一個Thread對象都代表一個新的線程。


       Java中實現線程有兩種方法:

       1、繼承Thread類,並且重寫其run方法(用來封裝整個線程要執行的命令),調用start方法啟動線程。

       比如下面這個類T要實現線程,則代碼如下:

public class CreateThreadTest{public static void main(String[] args) {T r=new T();r.start();   //T類的線程開始執行for(int i=0;i<100;i++){System.out.println("主線程正在執行~~~~"+i);}}}class T extends Thread{public void run(){//重寫父類中的run方法for(int i=0;i<100;i++){System.out.println("我建立的線程正在執行~~~~"+i);}}}
       現在,這一個小程式一共有兩個線程正在執行,一個是主線程,還有一個是T類建立的線程。

        

        2、實現Runnable介面

        還有一種方法就是讓實現線程的類實現Runnable介面,實現Runnable介面中唯一的方法run(),然後把此類的執行個體當做Thread類的建構函式的參數,建立線程對象。

        例如上面的例子,還可以這樣寫:

public class CreateThreadTest {public static void main(String[] args) {T r=new T();Thread t=new Thread(r);    //建立線程對象t.start();    //T類的線程開始for(int i=0;i<100;i++){System.out.println("主線程正在執行~~~~"+i);}}}class T implements Runnable {public void run(){for(int i=0;i<100;i++){System.out.println("我建立的線程正在執行~~~~"+i);}}}

       兩種方法的實質就是,都需要重寫run方法,最終都是由Thread類的start方法啟動線程。

       溫馨提示:因為Java中不支援多繼承,所以實現線程時,一旦繼承了Thread類,就無法再繼承其他類了。但Java支援實現多個介面,所以推薦採用第二中方法,比較靈活。


       多線程

       多線程主要是為了同步完成多項任務,即同時執行多個線程。多線程把一個進程劃分為多個任務,它們彼此獨立地工作

       我們都知道,現在大部分作業系統比如Windows、Mac OS X、Unix、Linux等,都是支援多線程的,但我們平時所說的多線程,並不意味著CPU在同時會處理多個線程,每個CPU在同一個時間點只會處理一個線程,只不過速度太快了,處理的時間極短,以至於我們可以認為它是在同一個時間段可以處理多個線程。所以只有當你的機器是“雙核”甚至“多核”時,才能實現真正意義上的多線程。                                                                                            

         

       下面看一個多線程的例子:

        兩個線程t1和t2的執行        

public class ThreadTest {public static void main(String[] args) {Thread t1=new Thread(new T1());Thread t2=new Thread(new T2());t1.start();t2.start();}}class T1 implements Runnable{public void run(){for(int i=0;i<10;i++){System.out.println("線程1正在執行中------"+i);if(i==9){System.out.println("線程1執行已結束------"+i);break;}}}}class T2 implements Runnable{public void run(){for(int i=0;i<10;i++){System.out.println("線程2正在執行中------"+i);if(i==9){System.out.println("線程2執行已結束------"+i);break;}}}}
         看下面的結果之前,先充分發揮你的大腦想一想到底結果應該是什麼樣子的~~

         執行結果:

          

       是不是跟您預測的不一樣呢?如果不加線程的話,本來的結果應該前十行都是線程1在執行,線程1執行完後線程2才開始執行,線程調度演算法使得每個線程執行一會進入等待狀態,再去執行另一個線程。

         

       線程中常用的方法

       如果親手嘗試過上面這個例子中,會發現這兩個線程t1和t2誰先執行,誰後執行,誰執行多長時間等等這些都是不確定、不可控的。下面就說一下線程中常用到的幾個方法。

       ★ void yield()方法

       在一個線程中,如果執行到yield()方法,那麼這個線程就會讓出CPU資源,暫停當前正在執行的線程對象,轉而讓CPU去執行其他具有相同優先順序的線程。充分體現了線程樂于謙讓的精神!

       例:i的值從0到99,每次輸出線程執行個體的名字,當i是10的倍數時,執行yield方法。 

 public class TestYield {public static void main(String[] args) {MyThread thread1=new MyThread("thread1");MyThread thread2=new MyThread("thread2");thread1.start();thread2.start();}}class MyThread extends Thread{MyThread(String name){super(name);}public void run(){for(int i=0;i<100;i++){System.out.println(getName()+":"+i);if(i%10==0){yield();}}}}
       從結果中的前幾條輸出可以發現,對thread1來說,每當i是10的倍數時,進程就會讓出,thread2進程執行;thread2也是如此:

          

      注意: yield()方法會將當前啟動並執行線程切換到可運行狀態,但可能沒有效果,因為實際中執行yield方法的線程還有可能被發送器再次選中。

        

      ★ void sleep(long millis)方法和void sleep(long millis,int nanos)

       讓線程休眠(暫停執行)指定的時間長度,參數millis的單位是毫秒,參數nanos的單位是納秒。線程執行了sleep方法後就會進入阻塞狀態,指定的時間段過後,線程進入可執行狀態,等待被作業系統調度。

       例:      

import java.util.*;public class TestSleep {public static void main(String[] args){MyThread thread=new MyThread();thread.start();}}class MyThread extends Thread{public void run(){while(true){System.out.println("==="+new Date()+"===");try{sleep(1000);}catch(InterruptedException e){return;}}}}
        看完代碼您應該猜到結果了,每隔一秒都會輸出目前時間,相當於一個定時器。這個程式一共有兩個線程,主線程(即main方法)中出了執行thread線程就沒有其他任務需要執行,所以這裡可以看做只執行thread這一個線程,如果把例子中的sleep方法去掉,那麼就會“唰唰唰”地不斷輸出目前時間(你的CPU風扇也會“唰唰唰”~~~~)。

       

         ★void join()方法

         上面說線程執行了yield方法時,會自動讓出CPU資源,使狀態由運行狀態轉換為可運行狀態。join()方法可以說是恰恰相仿,當一個線程執行了join方法時,那麼它就會一直執行下去直到這個線程結束。

        還是舉例來說明:

public class TestJoin {      public static void main(String[] args) throws InterruptedException {          Thread t1 = new Thread(new ThreadA());          Thread t2 = new Thread(new ThreadB());          t1.start();          t1.join(); // t1線程開始執行後,它將繼續執行下去,直到t1線程結束,否則絕不讓出CPU          t2.start();          t2.join(); // t2線程開始執行後,它將繼續執行下去,直到t1線程結束,否則絕不讓出CPU      }  }class ThreadA implements Runnable {       public void run() {          for (int i=0;i<10;i++) {              System.out.println("A線程正在運行~~~~" + i);          }       }  }   class ThreadB implements Runnable {   public void run() {          for (int i=0;i<10;i++) {              System.out.println("B線程正在運行~~~~" + i);          }       }   } 
       先來設想一下,加入t1和t2兩個線程啟動後不執行join方法,那麼CPU給它們分配的執行時間和順序就不一定相同,如左;如果t1和t2執行了join方法,那麼它們一旦開始執行,就將執行到底,如右。

                  
       

        為什麼要用多線程

        最後一個問題,為什麼要用多線程?

        在論壇裡看到一個大牛的比喻:單線程就是牛逼老闆從頭到尾一個人做完,另開一個線程就是老闆掰出一件事情叫一個小弟去做,這個小弟的進入會加快整個事情的進展,但有時可能會做起事來礙手礙腳。


       當然,想要更深地理解多線程的精髓所在,光靠學這些理論還是不夠的,更重要的還是在實踐和項目中去挖掘和思考。


J2SE快速進階——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.