多線程

概念:

1.進程:

    定義:在一個操作系統中,每個獨立運行的程序都可以稱爲一個進程,也就是“正在運行的程序”。
    
    在多任務操作系統中,表面上看是支持進程併發執行的,但實際上這些進程並不是同時運行的。

2.線程:

    定義:每個運行的程序都是一個進程,在一個進程中還可以有多個單元同時運行,這些執行單元可以看做程序執行的一條條線索,這些線索被稱爲線程。

    操作系統中的每一個進程中至少存在一個線程。當一個Java程序啓動時,就會產生一個進程,該進程會默認創建一個線程,在這個線程上會運行main()方法中的代碼。

線程的創建:

    java中實現多線程有兩種方式,一種是繼承java.long包下的Thread類,覆寫Thread類的run()方法,在run()方法中實現運行在線程上的代碼;另一種是實現java.long.Runnable接口,同樣是在run()方法中實現運行在線程上的代碼。

    1.繼承Thread類創建多線程

        在學習多線程之前,先來看看我們所熟悉的單線程程序:
        Example01:
        
  1. public class Example01 {
  2. public static void main(String[] args) {
  3. MyThread myThread=new MyThread(); // 創建MyThread實例對象
  4. myThread.run(); // 調用MyThread類的run()方法
  5. while (true) { // 該循環是一個死循環,打印輸出語句
  6. System.out.println("Main方法在運行");
  7. }
  8. }
  9. }
  10. class MyThread {
  11. public void run() {
  12. while (true) { // 該循環是一個死循環,打印輸出語句
  13. System.out.println("MyThread類的run()方法在運行");
  14. }
  15. }
  16. }
        運行結果如下所示:
        

概念:

1.進程:

    定義:在一個操作系統中,每個獨立運行的程序都可以稱爲一個進程,也就是“正在運行的程序”。
    
    在多任務操作系統中,表面上看是支持進程併發執行的,但實際上這些進程並不是同時運行的。

2.線程:

    定義:每個運行的程序都是一個進程,在一個進程中還可以有多個單元同時運行,這些執行單元可以看做程序執行的一條條線索,這些線索被稱爲線程。

    操作系統中的每一個進程中至少存在一個線程。當一個Java程序啓動時,就會產生一個進程,該進程會默認創建一個線程,在這個線程上會運行main()方法中的代碼。

線程的創建:

    java中實現多線程有兩種方式,一種是繼承java.long包下的Thread類,覆寫Thread類的run()方法,在run()方法中實現運行在線程上的代碼;另一種是實現java.long.Runnable接口,同樣是在run()方法中實現運行在線程上的代碼。

    1.繼承Thread類創建多線程

        在學習多線程之前,先來看看我們所熟悉的單線程程序:
        Example01:
        
  1. public class Example01 {
  2. public static void main(String[] args) {
  3. MyThread myThread=new MyThread(); // 創建MyThread實例對象
  4. myThread.run(); // 調用MyThread類的run()方法
  5. while (true) { // 該循環是一個死循環,打印輸出語句
  6. System.out.println("Main方法在運行");
  7. }
  8. }
  9. }
  10. class MyThread {
  11. public void run() {
  12. while (true) { // 該循環是一個死循環,打印輸出語句
  13. System.out.println("MyThread類的run()方法在運行");
  14. }
  15. }
  16. }
        運行結果如下所示:
        
         從上圖可以看出,程序一直打印的是“MyThread類的run()方法在運行”,這是因爲該程序是一個單線程程序,當調用MyThread類的run()方法時,遇到死循環,循環會一直進行。因此,MyThread類的打印語句將永遠執行,而main()方法中的打印語句無法得到執行。
        如果希望上述代碼中兩個while循環中的打印語句能夠併發執行,就需要實現多線程。
        Example02:
  1. public class Example02 {
  2. public static void main(String[] args) {
  3. MyThread myThread = new MyThread(); // 創建線程MyThread的線程對象
  4. myThread.start(); // 開啓線程
  5. while (true) { // 通過死循環語句打印輸出
  6. System.out.println("main()方法在運行");
  7. }
  8. }
  9. }
  10. class MyThread extends Thread {
  11. public void run() {
  12. while (true) { // 通過死循環語句打印輸出
  13. System.out.println("MyThread類的run()方法在運行");
  14. }
  15. }
  16. }
運行結果如下:
 從上述結果看,兩個while循環中的打印語句輪流執行了,說明該例子實現了多線程。

分析:單線程的程序在運行時,會按照代碼的調用順序進行執行。而在多線程中,main()方法和MyThread類的run()方法卻可以同時運行互不影響,這正是單線程與多線程的區別。

實現Runnable接口創建多線程


    通過繼承Thread類有一定侷限性。因爲Java中只支持單繼承,一個類一旦繼承了某個父類就無法再繼承Thread類。爲了克服這種弊端,Thread類提供了另外一種構造方法Thread(Runnable target),其中Runnable是一個接口,他只有一個run()方法。當通過Thread(Runnable target)構造方法創建線程對象時,只需要爲該方法傳遞一個實現了Runnable接口的實例對象,這樣創建線程將調用實現了Runnable接口中的run()方法作爲運行代碼,而不需要調用Thread類的run()方法,接下來通過一個案例來演示如何通過實現Runnable接口的方式來創建多線程,如下所示:
Example03:
  1. public class Example03 {
  2. public static void main(String[] args) {
  3. MyThread myThread = new MyThread(); // 創建MyThread的實例對象
  4. Thread thread=new Thread(myThread); // 創建線程對象
  5. thread.start(); // 開啓線程,執行線程中的run()方法
  6. while (true) {
  7. System.out.println("main()方法在運行");
  8. }
  9. }
  10. }
  11. class MyThread implements Runnable {
  12. public void run() { // 線程的代碼段,當調用start()方法時,線程從此處開始執行
  13. while (true) {
  14. System.out.println("MyThread類的run()方法在運行");
  15. }
  16. }
  17. }

運行結果如下所示:
 MyThread類實現了Runnable接口,並重寫了Runnable接口中的run()方法,通過Thread類的構造方法將MyThread類的實力對象作爲參數傳入。從運行結果看出該例實現了多線程。
        

後臺線程

    對java程序來說,只要還有一個前臺進程在運行,這個進程就不會結束,如果一個進程中只有後臺線程雲心,這個進程就會結束。這裏提到的前臺線程和後臺線程是一種相對的概念,新創建的線程默認都是前臺線程,如果某個線程對象在啓動之前調用了setDeamon(true)語句,這個線程就會變成一個後臺線程。
Example04
  1. class DamonThread implements Runnable { // 創建DamonThread類,實現Runnable接口
  2. public void run() { // 實現接口中的run()方法
  3. while (true) {
  4. System.out.println(Thread.currentThread().getName()
  5. + "---is running.");
  6. }
  7. }
  8. }
  9. public class Example04 {
  10. public static void main(String[] args) {
  11. System.out.println("main線程是後臺線程嗎?"+ Thread.currentThread().isDaemon());//通過Thread的currentThread()方法得到當前線程對象
  12. DamonThread dt = new DamonThread(); // 創建一個DamonThread對象dt
  13. Thread t = new Thread(dt,"後臺線程"); // 創建線程t共享dt資源
  14. System.out.println("t線程默認是後臺線程嗎? "+t.isDaemon()); // 判斷是否爲後臺線程
  15. t.setDaemon(true); // 將線程t設置爲後臺線程
  16. t.start(); // 調用start()方法開啓線程t
  17. for(int i=0;i<10;i++){
  18. System.out.println(i);
  19. }
  20. }
  21. }

運行結果如下所示:
 該示例演示了一個後臺線程結束的過程。當開啓線程t時,會執行死循環中的打印語句,但我們將線程t設置爲後臺線程後,當前臺線程死亡後,JVM會通知後臺線程。由於後臺線程從接受指令到作出相應需要一段時間,因此打印了幾次“後臺線程---is running.”語句後,後臺線程也結束了。由此說明進程中只有後臺線程運行時,程序就會結束。

   注意:將某個線程設置爲後臺線程,必須在該線程啓動之前,也就是說setDeamon()方法必須在start()方法之前調用,否則就會引發IllegalThreadStateException異常。

         從上圖可以看出,程序一直打印的是“MyThread類的run()方法在運行”,這是因爲該程序是一個單線程程序,當調用MyThread類的run()方法時,遇到死循環,循環會一直進行。因此,MyThread類的打印語句將永遠執行,而main()方法中的打印語句無法得到執行。
        如果希望上述代碼中兩個while循環中的打印語句能夠併發執行,就需要實現多線程。
        Example02:
  1. public class Example02 {
  2. public static void main(String[] args) {
  3. MyThread myThread = new MyThread(); // 創建線程MyThread的線程對象
  4. myThread.start(); // 開啓線程
  5. while (true) { // 通過死循環語句打印輸出
  6. System.out.println("main()方法在運行");
  7. }
  8. }
  9. }
  10. class MyThread extends Thread {
  11. public void run() {
  12. while (true) { // 通過死循環語句打印輸出
  13. System.out.println("MyThread類的run()方法在運行");
  14. }
  15. }
  16. }
運行結果如下:
 從上述結果看,兩個while循環中的打印語句輪流執行了,說明該例子實現了多線程。

分析:單線程的程序在運行時,會按照代碼的調用順序進行執行。而在多線程中,main()方法和MyThread類的run()方法卻可以同時運行互不影響,這正是單線程與多線程的區別。

實現Runnable接口創建多線程


    通過繼承Thread類有一定侷限性。因爲Java中只支持單繼承,一個類一旦繼承了某個父類就無法再繼承Thread類。爲了克服這種弊端,Thread類提供了另外一種構造方法Thread(Runnable target),其中Runnable是一個接口,他只有一個run()方法。當通過Thread(Runnable target)構造方法創建線程對象時,只需要爲該方法傳遞一個實現了Runnable接口的實例對象,這樣創建線程將調用實現了Runnable接口中的run()方法作爲運行代碼,而不需要調用Thread類的run()方法,接下來通過一個案例來演示如何通過實現Runnable接口的方式來創建多線程,如下所示:
Example03:
  1. public class Example03 {
  2. public static void main(String[] args) {
  3. MyThread myThread = new MyThread(); // 創建MyThread的實例對象
  4. Thread thread=new Thread(myThread); // 創建線程對象
  5. thread.start(); // 開啓線程,執行線程中的run()方法
  6. while (true) {
  7. System.out.println("main()方法在運行");
  8. }
  9. }
  10. }
  11. class MyThread implements Runnable {
  12. public void run() { // 線程的代碼段,當調用start()方法時,線程從此處開始執行
  13. while (true) {
  14. System.out.println("MyThread類的run()方法在運行");
  15. }
  16. }
  17. }

運行結果如下所示:
 MyThread類實現了Runnable接口,並重寫了Runnable接口中的run()方法,通過Thread類的構造方法將MyThread類的實力對象作爲參數傳入。從運行結果看出該例實現了多線程。
        

後臺線程

    對java程序來說,只要還有一個前臺進程在運行,這個進程就不會結束,如果一個進程中只有後臺線程雲心,這個進程就會結束。這裏提到的前臺線程和後臺線程是一種相對的概念,新創建的線程默認都是前臺線程,如果某個線程對象在啓動之前調用了setDeamon(true)語句,這個線程就會變成一個後臺線程。
Example04
  1. class DamonThread implements Runnable { // 創建DamonThread類,實現Runnable接口
  2. public void run() { // 實現接口中的run()方法
  3. while (true) {
  4. System.out.println(Thread.currentThread().getName()
  5. + "---is running.");
  6. }
  7. }
  8. }
  9. public class Example04 {
  10. public static void main(String[] args) {
  11. System.out.println("main線程是後臺線程嗎?"+ Thread.currentThread().isDaemon());//通過Thread的currentThread()方法得到當前線程對象
  12. DamonThread dt = new DamonThread(); // 創建一個DamonThread對象dt
  13. Thread t = new Thread(dt,"後臺線程"); // 創建線程t共享dt資源
  14. System.out.println("t線程默認是後臺線程嗎? "+t.isDaemon()); // 判斷是否爲後臺線程
  15. t.setDaemon(true); // 將線程t設置爲後臺線程
  16. t.start(); // 調用start()方法開啓線程t
  17. for(int i=0;i<10;i++){
  18. System.out.println(i);
  19. }
  20. }
  21. }

運行結果如下所示:
 該示例演示了一個後臺線程結束的過程。當開啓線程t時,會執行死循環中的打印語句,但我們將線程t設置爲後臺線程後,當前臺線程死亡後,JVM會通知後臺線程。由於後臺線程從接受指令到作出相應需要一段時間,因此打印了幾次“後臺線程---is running.”語句後,後臺線程也結束了。由此說明進程中只有後臺線程運行時,程序就會結束。

   注意:將某個線程設置爲後臺線程,必須在該線程啓動之前,也就是說setDeamon()方法必須在start()方法之前調用,否則就會引發IllegalThreadStateException異常。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章