1. 程式人生 > >java核心學習(二十一) 多線程---創建啟動線程的三種方式

java核心學習(二十一) 多線程---創建啟動線程的三種方式

使用 trace 啟動 操作系統 java多線程 start name image 獲取

   本節開始java多線程編程的學習,對於操作系統、進程、線程的基本概念不再贅述,只是了解java對於多線程編程的支持有哪些。

一、繼承Thread類來創建線程

   java語言中使用Thread類來代表線程,代表線程的類可以通過繼承Thread類並重寫run()方法來實現多線程開發,調用線程類實例的start方法來啟動該線程。下面來試一試

 

package ThreadTest;

public class FirstThread extends Thread{
    private int i;
    public void run(){
        for(;i<100;i++){
            System.out.println(getName() 
+ " "+i); } } public static void main(String[] args){ for(int i = 0; i<10000 ; i++){ //Thread.currentThread()方法,獲取當前線程實例 System.out.println(Thread.currentThread().getName() + " " +i); if(i == 20){ new FirstThread().start();
new FirstThread().start(); } } } }

    輸出結果可想而知,三個線程交替運行。其中mian線程是Thread-0 和 Thread-1的父親線程,使用繼承Thread類的線程類來創建線程時,多個線程無法共享線程類的實例變量。

二、實現Runnable接口來創建線程類

  Runnable接口中只有一個抽象方法 void run(),是一個函數式接口。如果打開Thread類的代碼,就可以發現Thread類也是實現了Runnable接口。

  實現Runnable接口的run()方法的類只能算一個target,只是為線程提供了run方法,要真正創建線程必須調用Thread的構造方法來創建Thread,其實也是使用了Thread來創建線程。

  下面來試一試

package ThreadTest;

public class SecondThread implements Runnable{
    private int i;
    public void run(){
        for(;i<100;i++){
            System.out.println(Thread.currentThread().getName()+ " " +i);
        }
    }
    public static void main(String[] args)
    {
        for(int i = 0;i<100;i++){
            
            System.out.println(Thread.currentThread().getName()+ " "+ i);
            if(i==20){
                Runnable st = new SecondThread();
                new Thread(st,"自定義名字").start();
            }
        }
    }
}

  技術分享技術分享

    這是Thread的run方法,可以看到Thread調用了Runnable實現類的run方法。

三、使用Callable 和 Future創建線程

  Callable接口只有一個call()抽象方法,與run()不同的是call()有返回值,可以拋出異常

  下圖是Callable接口定義

  技術分享

  泛型V代表了call方法的返回值類型

  那麽如何把實現了Callable接口的類的call方法當做線程執行體呢,如何獲取call方法的返回值呢?

  這需要用到Future,Future接口代表call()方法的返回值,調用Future實例的get方法可以去的返回值,對應於Callable接口,Future也支持泛型。

  還需要用到FutureTask類,這個類實現了Future接口和Runnable,可以獲取到返回值,也可以作為線程創建的target

技術分享

技術分享

  FutureTask的構造器

技術分享

技術分享

  FutureTask的run方法

技術分享

  下面用一下

package ThreadTest;

import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;

public class ThirdThread{
    public static void main(String[] args){
        ThirdThread tt = new ThirdThread();
        FutureTask<Integer> task = new FutureTask<Integer>(new Callable<Integer>() {
            @Override
            public Integer call() throws Exception {
                int i =0;
                for(;i<100;i++){
                    System.out.println(Thread.currentThread().getName() + " " + i);
                }
                return i;
            }
        });
        for (int i = 0;i<100;i++){
            System.out.println(Thread.currentThread().getName()+" "+i);
            if(i == 20){
                new Thread(task,"帶返回值的線程").start();
            }
            try {
                System.out.println("子線程返回值:" + task.get());
            }catch (Exception ex){
                ex.printStackTrace();
            }
        }
    }
}

    這裏要註意,調用FutureTask方法的get方法時,當前線程在取得返回值之前會被阻塞。

    通常使用後兩種方式來創建線程

java核心學習(二十一) 多線程---創建啟動線程的三種方式