Java基礎之多線程框架(二)

1、前言   

      當一個Java程序啓動的時候,一個線程就馬上啓動,改程序一般也被咱們稱做程序的主線程。其餘全部的子線程都是由主線程產生的。主線程是程序開始就執行的,而且程序最終是以主線程的結束而結束的。java

      Java編寫程序都運行在在Java虛擬機(JVM)中,在JVM的內部,程序的多任務是經過線程來實現的。每用Java命令啓動一個Java應用程序,就會啓動一個JVM進程。在同一個JVM進程中,有且只有一個進程,就是它本身。在這個JVM環境中,全部程序代碼的運行都是以線程來運行。多線程

2、多線程的概念 框架

      一般,咱們接觸的簡單的程序都是單線程的,可是若是咱們須要進行「多線操做」的話,就須要藉助多線程來實現了,對於一個進程中的多個線程來講,多個線程共享進程的內存塊,當有新的線程產生的時候,操做系統不分配新的內存,而是讓新線程共享原有的進程塊的內存。所以,線程間的通訊很容易,速度也很快。不一樣的進程由於處於不一樣的內存塊,所以進程之間的通訊相對困難。this

     在Java中,多線程的實現有兩種方式:繼承java.lang.Thread類;實現java.lang.Runnable接口。spa

3、繼承Thread類來實現多線程操作系統

      當一個類繼承Thread類時,在類中必須重載run()方法,同時這個run()方法也是線程的入口,在調用的過程當中,經過調用start()方法來啓動新線程,其基本框架爲:線程

1 class 類名 extends Thread{
 2 方法1;
 3 方法2;
 4 …
 5 public void run(){
 6 // other code…
 7 }
 8 屬性1;
 9 屬性2;
10 …
11  
12 }

        在這裏,咱們用一個簡單的窗口買票的例子來實現此類多線程設計

1 class TestThread extends Thread
 2 {
 3     private String name;
 4     public TestThread(String name)
 5     {
 6         this.name=name;
 7     }
 8     public void run()
 9     {
10 
11         for (int i = 0; i < 7; i++)
12         {
13             if (num > 0)
14             {
15                 System.out.println(name+"正在賣票  "+"num= " + num--);
16             }
17         }
18     }
19 
20 
21     public static void main(String[] args)
22     {
23 
24         TestThread h1 = new TestThread("窗口1");
25         TestThread h2 = new TestThread("窗口2");
26         TestThread h3 = new TestThread("窗口3");
27         h1.start();
28         h2.start();
29         h3.start();
30     }
31 
32     private int num = 5;
33 }

      在這個簡單的例子中,能夠很清楚的看到繼承Thread實現多線程的實現已經調用,本例中運行的結果爲:code

1 窗口1正在賣票  num= 5
 2 窗口1正在賣票  num= 4
 3 窗口1正在賣票  num= 3
 4 窗口1正在賣票  num= 2
 5 窗口1正在賣票  num= 1
 6 窗口2正在賣票  num= 5
 7 窗口2正在賣票  num= 4
 8 窗口2正在賣票  num= 3
 9 窗口2正在賣票  num= 2
10 窗口2正在賣票  num= 1
11 窗口3正在賣票  num= 5
12 窗口3正在賣票  num= 4
13 窗口3正在賣票  num= 3
14 窗口3正在賣票  num= 2
15 窗口3正在賣票  num= 1

      而且這個結果有必定的不可預知性,咱們不可以肯定線程之間執行的具體順序,同時,更爲重要的,經過繼承Thread實現多線程不可以實現資源的共享,以購票爲例子,假設票的總數爲5張的話,咱們只能經過一個窗口來賣完這5張票,或者說,咱們開設了三個窗口,但這個三個窗口都有5張票,這顯然和咱們的設計理念是有點差異的。因此,實現多線程的時候,我更喜歡使用實現Runnable接口的方法。對象

4、實現Runnable接口來實現多線程

       和繼承Thread相似,當一個類實現Runnable接口時,在類中也必須重載run()方法,同時這個run()方法也是線程的入口,在調用的過程當中,經過調用start()方法來啓動新線程,其基本框架爲:

1 class 類名 implements Runnable{
 2 方法1;
 3 方法2;
 4 …
 5 public void run(){
 6 // other code…
 7 }
 8 屬性1;
 9 屬性2;
10 …
11  
12 }

         在調用的時候會稍微有一些區別,仍是以簡單的窗口買票來舉例說明:

1 class MyThread implements Runnable
 2 {
 3  
 4     private int ticket = 5;  //5張票
 5  
 6     public void run() 
 7     {
 8         for (int i=0; i<=20; i++) 
 9         {
10             if (this.ticket > 0) 
11             {
12                 System.out.println(Thread.currentThread().getName()+ "正在賣票"+this.ticket--);
13             }
14         }
15     }
16 }
17 public class TestThread {
18      
19     public static void main(String [] args) 
20     {
21         MyThread my = new MyThread();
22         new Thread(my, "1號窗口").start();
23         new Thread(my, "2號窗口").start();
24         new Thread(my, "3號窗口").start();
25     }
26 }

       程序執行的結果爲:

1 1號窗口正在賣票5
2 1號窗口正在賣票4
3 1號窗口正在賣票3
4 2號窗口正在賣票2
5 1號窗口正在賣票1

       因而,咱們看到了咱們預先設定的效果,也就是說經過實現Runnable接口的方法,咱們實現的資源的共享。

5、小結

     在繼承Thread類實現多線程時,咱們建立了三個不一樣的對象,因此建立的三個線程其實是完成的三個不一樣的任務,因此纔會相互獨立的完成;而經過實現Runable接口來實現多線程時,咱們只建立了一個對象,而後實例化三個不一樣的線程去完成這個任務,因此至關因而共同完成任務。

     其實,其實Thread類也是實現Runnable接口的,其源代碼以下:

1 class Thread implements Runnable {
2     //…
3 public void run() {
4         if (target != null) {
5              target.run();
6         }
7         }
8 }

      Thread中的run方法其實就是調用的是Runnable接口的run方法。方法是死的,人是活的,具體使用,能夠根據實際狀況來選擇。若是一個類繼承Thread,則不適合資源共享。可是若是實現了Runable接口的話,則突破了Java中單繼承的限制,很容易的實現資源共享。

相關文章
相關標籤/搜索