進程是程序的一次動態執行過程,它須要經歷從代碼加載,代碼執行到執行完畢的一個完整的過程,這個過程也是進程自己從產生,發展到最終消亡的過程。多進程操做系統能同時達運行多個進程(程序),因爲CPU具有分時機制,因此每一個進程都能循環得到本身的CPU時間片。因爲CPU執行速度很是快,使得全部程序好像是在同時運行同樣。java
多線程是實現併發機制的一種有效手段。進程和線程同樣,都是實現併發的一個基本單位。線程是比進程更小的執行單位,線程是進程的基礎之上進行進一步的劃分。所謂多線程是指一個進程在執行過程當中能夠產生多個更小的程序單元,這些更小的單元稱爲線程,這些線程能夠同時存在,同時運行,一個進程可能包含多個同時執行的線程。進程與線程的區別如圖所示:多線程
在Java中實現多線程有兩種手段,一種是繼承Thread類,另外一種就是實現Runnable接口。下面咱們就分別來介紹這兩種方式的使用。併發
public class ThreadDemo { public static void main(String[] args) { MyThread threadA=new MyThread("線程A"); MyThread threadB=new MyThread("線程B"); Thread t1=new Thread(threadA); Thread t2=new Thread(threadB); t1.start(); t2.start(); } } class MyThread implements Runnable{ private String name; int i=0; public MyThread(String name) { this.name = name; } @Override public void run() { while(i<10){ System.out.println(name+" i:"+i); i++; } } }
運行結果ide
線程A i:0 線程B i:0 線程A i:1 線程B i:1 線程A i:2 線程B i:2 線程A i:3 線程B i:3 線程A i:4 線程B i:4 線程A i:5 線程B i:5 線程A i:6 線程B i:6 線程B i:7 線程A i:7 線程A i:8 線程A i:9 線程B i:8 線程B i:9
public class ThreadDemo { public static void main(String[] args) { MyThread threadA=new MyThread("線程A"); MyThread threadB=new MyThread("線程B"); Thread t1=new Thread(threadA); Thread t2=new Thread(threadB); t1.start(); t2.start(); } } class MyThread extends Thread{ private String name; int i=0; public MyThread(String name) { this.name = name; } @Override public void run() { while(i<10){ System.out.println(name+" i:"+i); i++; } } }
運行結果this
線程B i:0 線程B i:1 線程B i:2 線程B i:3 線程B i:4 線程B i:5 線程B i:6 線程B i:7 線程B i:8 線程B i:9 線程A i:0 線程A i:1 線程A i:2 線程A i:3 線程A i:4 線程A i:5 線程A i:6 線程A i:7 線程A i:8 線程A i:9
兩個線程,哪一個線程搶到了CPU執行權,就執行那個線程。線程調用start()方法,實際上執行的是run()方法體中的主體。spa
public class Thread extends Object implements Runnable操作系統
從Thread類的定義能夠清楚的發現,Thread類也是Runnable接口的子類,但在Thread類中並無徹底實現Runnable接口中的run()方法,下面是Thread類的部分定義。.net
Private Runnable target; public Thread(Runnable target,String name){ init(null,target,name,0); } private void init(ThreadGroup g,Runnable target,String name,long stackSize){ ... this.target=target; } public void run(){ if(target!=null){ target.run(); } }
從定義中能夠發現,在Thread類中的run()方法調用的是Runnable接口中的run()方法,也就是說此方法是由Runnable子類完成的,因此若是要經過繼承Thread類實現多線程,則必須覆寫run()。線程
實際上Thread類和Runnable接口之間在使用上也是有區別的,若是一個類繼承Thread類,則不適合於多個線程共享資源,而實現了Runnable接口,就能夠方便的實現資源的共享。code
要想實現多線程,必須在主線程中建立新的線程對象。任何線程通常具備5種狀態,即建立,就緒,運行,阻塞,終止。下面分別介紹一下這幾種狀態
建立狀態
在程序中用構造方法建立了一個線程對象後,新的線程對象便處於新建狀態,此時它已經有了相應的內存空間和其餘資源,但還處於不可運行狀態。新建一個線程對象可採用Thread類的構造方法來實現,例如「Thread thread=new Thread()」。
就緒狀態
新建線程對象後,調用該線程的start()方法就能夠啓動線程。當線程啓動時,線程進入就緒狀態。此時,線程將進入線程隊列排隊,等待CPU服務,這代表它已經具有了運行條件。
運行狀態
當就緒狀態被調用並得到處理器資源時,線程就進入了運行狀態。此時,自動調用該線程對象的run()方法。run()方法定義該線程的操做和功能。
阻塞狀態
一個正在執行的線程在某些特殊狀況下,如被人爲掛起或須要執行耗時的輸入/輸出操做,會讓CPU暫時停止本身的執行,進入阻塞狀態。在可執行狀態下,若是調用sleep(),suspend(),wait()等方法,線程都將進入阻塞狀態,發生阻塞時線程不能進入排隊隊列,只有當引發阻塞的緣由被消除後,線程才能夠轉入就緒狀態。
死亡狀態
線程調用stop()方法時或run()方法執行結束後,即處於死亡狀態。處於死亡狀態的線程不具備繼續運行的能力。
Java程序每次運行至少啓動幾個線程?
回答:至少啓動兩個線程,每當使用Java命令執行一個類時,實際上都會啓動一個JVM,每個JVM實際上就是在操做系統中啓動一個線程,Java自己具有了垃圾的收集機制。因此在Java運行時至少會啓動兩個線程,一個是main線程,另一個是垃圾收集線程。
public class ThreadDemo { public static void main(String[] args) { MyThread myThread=new MyThread(); new Thread(myThread,"線程A").start(); new Thread(myThread,"線程B").start(); } } class MyThread implements Runnable{ public void run() { for (int i = 0; i <3 ; i++) { System.out.println("當前線程名稱:"+Thread.currentThread().getName()); } } }