java 多線程

進程與線程的理解:

程是指:一個內存中運行的應用程序,每個進程都有自己獨立的一塊內存空間,一個進程中可以啓動多個線程。比如在Windows系統中,一個運行的exe就是一個進程。

線程是指:進程中的一個執行流程,一個進程中可以運行多個線程。比如java.exe進程中可以運行很多線程。線程總是屬於某個進程,進程中的多個線程共享進程的內存。


線程的狀態

1、線程共有下面5種狀態:

· 新建狀態(New):新創建了一個線程對象,當你用new創建一個線程時,該線程尚未運行。

· 就緒狀態(Runnable):線程對象創建後,其他線程調用了該對象的start()方法。該狀態的線程位於可運行線程池中,變得可運行,等待獲取CPU的使用權。

· 運行狀態(Running):就緒狀態的線程獲取了CPU,執行程序代碼。

· 阻塞狀態(Blocked):阻塞狀態是線程因爲某種原因放棄CPU使用權,暫時停止運行。直到線程進入就緒狀態,纔有機會轉到運行狀態。阻塞的情況分三種:

a. 等待阻塞:運行的線程執行wait()方法,JVM會把該線程放入等待池中。

b. 同步阻塞:運行的線程在獲取對象的同步鎖時,若該同步鎖被別的線程佔用,則JVM把該線程放入鎖。

c. 其他阻塞:運行的線程執行sleep()或join()方法,或者發出了I/O請求時,JVM會把該線程置爲阻塞狀態。當sleep()狀態超時、join()等待線程終止或者超時、或者I/O處理完畢時,線程重新轉入就緒狀態。

· 死亡狀態(Dead):

a.  由於run方法的正常退出而自然死亡;

b.  沒有捕獲到的異常事件終止了run方法的執行,從而導致線程突然死亡 

 

JAVA多線程實現方式

 JAVA多線程實現方式主要有以下三種:

1、繼承Thread

2、實現Runnable接口

比較:繼承Thread和實現Runnable接口都是創建線程的方法,唯一的區別在與java只允許單一繼承,但可以實現多個接口。

3、使用ExecutorServiceCallableFuture實現有返回結果的多線程。

 1、繼承Thread類實現多線程

     繼承Thread類的方法儘管被我列爲一種多線程實現方式,但Thread本質上也是實現了Runnable接口的一個實例,它代表一個線程的實例,並且,啓動線程的唯一方法就是通過Thread類的start()實例方法。start()方法是一個native方法,它將啓動一個新線程,並執行run()方法。這種方式實現多線程很簡單,通過自己的類直接extend Thread,並複寫run()方法,就可以啓動新線程並執行自己定義的run()方法。

例如:

Java代碼  

· package thread;  

·   

· public class MyThread extends Thread {  

·     public void run() {  

·         System.out.println("run()方法正在執行");  

·     }  

· }  

 

啓動線程方式如下:

Java代碼  

· MyThread myThread1 = new MyThread();  

· MyThread myThread2 = new MyThread();  

· myThread1.start();  

· myThread2.start();  

 

2、實現Runnable接口方式實現多線程

 

如果自己的類已經extends另一個類,就無法直接extends Thread,此時,必須實現一個Runnable接口。

方法如下:

Java代碼  

· package thread;  

· class OtherClass{  

·     public void print(String str){  

·         System.out.println(str);  

·     }  

· }  

·   

· public class MyThread extends OtherClass implements Runnable {  

·     public void run() {  

·         System.out.println("run()正在執行");  

·     }  

· }  

 

 

爲了啓動MyThread,需要首先實例化一個Thread,並傳入自己的MyThread實例。

具體方法如下:

Java代碼  

· MyThread myThread = new MyThread();  

· Thread thread = new Thread(myThread);  

· thread.start();  

 

 

事實上,當傳入一個Runnable target參數給Thread後,Threadrun()方法就會調用target.run(),參考JDK源代碼:

Java代碼  

· public void run() {  

·     if (target != null) {  

·         target.run();  

·     }  

· }  

 

學會了線程的創建方式,下面我們在舉幾個線程狀態轉換的例子


Java線程函數

 1創建線程,線程處於就緒新建狀態,但還沒有一個真正的線程

Thread(Runnable target) 
Thread(Runnable target, String name) 
Thread(ThreadGroup group, Runnable target) 
Thread(ThreadGroup group, Runnable target, String name) 
Thread(ThreadGroup group, Runnable target, String name, long stackSize)

啓動線程,線程處於運行狀態

start():啓動線程

3暫停線程,線程處於阻塞狀態

yield():暫定線程的執行,允許其它線程競爭CPU,常用於具有同等優先級的線程之間的競爭,適用於不支持時間分片的操作系統之間的線程處理。

sleeplong millis:線程休眠,暫停執行,但是不交出臨界區的鎖。

stop():kill一個線程,但是通常通過線程內的循環條件來結束一個線程。

public void interrupt() 中斷線程

4設置線程的優先級,低優先級的線程處於就緒狀態,還未獲得CPU使用的機會

setPriority(int weight):設置線程的優先級(1->10),值越高,優先級越高,一般是5,且子線程與母線程具有同等的優先級和線程屬性(是否爲前後臺線程)。

setDaemon(true):start()方法前執行,將該線程設置爲後臺線程,後臺線程在所有前臺線程執行完後亦自行終止。

5檢測線程的狀態

isAlive():判斷此線程是否處於處於活動狀態,如果在start()後,線程終止前,該方法返回true


線程狀態的轉換實例

Java代碼  

· package thread;  

·   

· public class ThreadStateDemo extends Thread {  

·   

·     Thread thread;  

·   

·     public ThreadStateDemo() {  

·         thread = new Thread(this);  

·         System.out.println("創建一個線程:thread");  

·         thread.start();  

·     }  

·   

·     public void run() {  

·        try {  

·            System.out.println("線程thread正在運行!");  

·            System.out.println("線程thread睡眠3秒中...!");  

·            Thread.sleep(3000);  //靜態方法,使當前正在執行的線程睡眠3  

·            System.out.println("線程thread在睡眠後重新運行!");  

·        }catch(InterruptedException e) {  

·            System.out.println("線程被中斷");  

·        }  

·     }  

·   

·     public static void main(String[] args) {  

·        new ThreadStateDemo();  

·        System.out.println("主線程main結束!");  

·     }  

· }  

 

線程的同步

同步就是協同步調,按預定的先後次序進行運行。

1線程相互影響

public class synchronize1 {

 

public static void main(String[] args)  {

// TODO Auto-generated method stub

           

      //共享代碼段

            Shared shared=new Shared();

            //創建進程

            CustomThread thread1=new CustomThread(shared,"one");

            CustomThread thread2=new CustomThread(shared,"two");

            CustomThread thread3=new CustomThread(shared,"three");

            CustomThread thread4=new CustomThread(shared,"four"); 

         try{

          //jion()方法使得當前線程暫停執行,等待調用該方法的線程結束後再繼續執行本線程

          thread1.join();

          thread2.join();

          thread3.join();

          thread4.join();

         }catch(InterruptedException e){}

  

}

}

 

class  CustomThread extends Thread{

Shared shared;

public  CustomThread(Shared shared,String string){

super(string);

this.shared=shared;

start();

}

public void run(){

shared.doWork(Thread.currentThread().getName());

}

}

 

class  CustomThread2 implements Runnable{

Shared shared;

Thread thread=new Thread();

public  CustomThread2(Shared shared,String string){

this.shared=shared;

thread.start();

}

public void join() throws InterruptedException {

// TODO Auto-generated method stub

thread.join();

}

public void run(){

shared.doWork(Thread.currentThread().getName());

}

}

//共享代碼段

class Shared{

void doWork(String string){

System.out.println("Strating "+string);

try{

Thread.sleep((long)(Math.random()*500));

}catch(InterruptedException e){}

System.out.println("Ending"+string);

}

}

 

2使用 synchronized關鍵字來聲明要禁止訪問的對象

 

public class synchronize2 {

 

public static void main(String[] args)  {

// TODO Auto-generated method stub

           

      //共享代碼段

            Shared shared=new Shared();

            //創建進程

            CustomThread thread1=new CustomThread(shared,"one");

            CustomThread thread2=new CustomThread(shared,"two");

            CustomThread thread3=new CustomThread(shared,"three");

            CustomThread thread4=new CustomThread(shared,"four"); 

         try{

          //jion()方法使得當前線程暫停執行,等待調用該方法的線程結束後再繼續執行本線程

          thread1.join();

          thread2.join();

          thread3.join();

          thread4.join();

         }catch(InterruptedException e){}

  

}

}

 

class  CustomThread extends Thread{

Shared shared;

public  CustomThread(Shared shared,String string){

super(string);

this.shared=shared;

start();

}

public void run(){

//實現同步

 synchronized(shared)

 {

shared.doWork(Thread.currentThread().getName());

 }

}

}

 

class  CustomThread2 implements Runnable{

Shared shared;

Thread thread=new Thread();

public  CustomThread2(Shared shared,String string){

this.shared=shared;

thread.start();

}

public void join() throws InterruptedException {

// TODO Auto-generated method stub

thread.join();

}

public void run(){

shared.doWork(Thread.currentThread().getName());

}

}

//共享代碼段

class Shared{

void doWork(String string){

System.out.println("Strating "+string);

try{

Thread.sleep((long)(Math.random()*500));

}catch(InterruptedException e){}

System.out.println("Ending"+string);

}

}

 

3使用 synchronized關鍵字來聲明要禁止訪問的方法,阻塞其他線程的通路,使某一時刻只有一個線程可以進入方法

 

public class synchronize3 {

 

public static void main(String[] args)  {

// TODO Auto-generated method stub

           

      //共享代碼段

            Shared shared=new Shared();

            //創建進程

            CustomThread thread1=new CustomThread(shared,"one");

            CustomThread thread2=new CustomThread(shared,"two");

            CustomThread thread3=new CustomThread(shared,"three");

            CustomThread thread4=new CustomThread(shared,"four"); 

         try{

          //jion()方法使得當前線程暫停執行,等待調用該方法的線程結束後再繼續執行本線程

          thread1.join();

          thread2.join();

          thread3.join();

          thread4.join();

         }catch(InterruptedException e){}

  

}

}

 

class  CustomThread extends Thread{

Shared shared;

public  CustomThread(Shared shared,String string){

super(string);

this.shared=shared;

start();

}

public void run(){

//實現同步

shared.doWork(Thread.currentThread().getName());

}

}

 

class  CustomThread2 implements Runnable{

Shared shared;

Thread thread=new Thread();

public  CustomThread2(Shared shared,String string){

this.shared=shared;

thread.start();

}

public void join() throws InterruptedException {

// TODO Auto-generated method stub

thread.join();

}

public void run(){

shared.doWork(Thread.currentThread().getName());

}

}

//共享代碼段

class Shared{

synchronized void doWork(String string){

System.out.println("Strating "+string);

try{

Thread.sleep((long)(Math.random()*500));

}catch(InterruptedException e){}

System.out.println("Ending"+string);

}

}


 

 線程間的通信

新建進程1,進程1開始運行,執行getResult(),進程1處於等待狀態

新建進程2,進程2開始運行,執行doWork(),進程2處於睡眠狀態,喚醒進程1,進程1輸出結果

public class communicat {

 

public static void main(String[] args)  {

// TODO Auto-generated method stub

           

      //共享代碼段

            Shared shared=new Shared();

            //創建進程

            CustomThread thread1=new CustomThread(shared,"one");

            CustomThread2 thread2=new CustomThread2(shared,"two");

  

}

}

 

class  CustomThread extends Thread{

Shared shared;

public  CustomThread(Shared shared,String string){

super(string);

this.shared=shared;

start();

}

public void run(){

//實現同步

System.out.println(shared.getResult());

}

}

 

class  CustomThread2 extends Thread{

Shared shared;

public  CustomThread2(Shared shared,String string){

super(string);

this.shared=shared;

start();

}

public void run(){

//實現同步

shared.doWork();

}

}

//共享代碼段

class Shared{

int data=0;

synchronized void doWork(){

try{

Thread.sleep((1000));

}catch(InterruptedException e){}

data=1;

notify();

}

synchronized int getResult(){

try{

wait();

}catch(InterruptedException e){}

return data;

}

}

 



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