多線程的幾種實現方式

https://blog.csdn.net/java_zyq/article/details/87917734

java多線程的幾種實現方式:
1.繼承Thread類,重寫run方法
2.實現Runnable接口,重寫run方法,實現Runnable接口的實現類的實例對象作爲Thread構造函數的target
3.通過Callable和FutureTask創建線程
4.通過線程池創建線程 

 

前面兩種可以歸結爲一類:無返回值,原因很簡單,通過重寫run方法,run方式的返回值是void,所以沒有辦法返回結果 
後面兩種可以歸結成一類:有返回值,通過Callable接口,就要實現call方法,這個方法的返回值是Object,所以返回的結果可以放在Object對象中

方式1:繼承Thread類的線程實現方式如下:

public class ThreadDemo01 extends Thread{
    public ThreadDemo01(){
        //編寫子類的構造方法,可缺省
    }
    public void run(){
        //編寫自己的線程代碼
        System.out.println(Thread.currentThread().getName());
    }
    public static void main(String[] args){ 
        ThreadDemo01 threadDemo01 = new ThreadDemo01(); 
        threadDemo01.setName("我是自定義的線程1");
        threadDemo01.start();       
        System.out.println(Thread.currentThread().toString());  
    }
}

程序結果: 
Thread[main,5,main] 
我是自定義的線程1

線程實現方式2:

通過實現Runnable接口,實現run方法,接口的實現類的實例作爲Thread的target作爲參數傳入帶參的Thread構造函數,通過調用start()方法啓動線程

public class ThreadDemo02 {
 
    public static void main(String[] args){ 
        System.out.println(Thread.currentThread().getName());
        Thread t1 = new Thread(new MyThread());
        t1.start(); 
    }
}
 
class MyThread implements Runnable{
    @Override
    public void run() {
        // TODO Auto-generated method stub
        System.out.println(Thread.currentThread().getName()+"-->我是通過實現接口的線程實現方式!");
    }   
}

程序運行結果: 
main 
Thread-0–>我是通過實現接口的線程實現方式!

線程實現方式3:通過Callable和FutureTask創建線程 
a:創建Callable接口的實現類 ,並實現Call方法 
b:創建Callable實現類的實現,使用FutureTask類包裝Callable對象,該FutureTask對象封裝了Callable對象的Call方法的返回值 
c:使用FutureTask對象作爲Thread對象的target創建並啓動線程 
d:調用FutureTask對象的get()來獲取子線程執行結束的返回值

public class ThreadDemo03 {
 
    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
 
        Callable<Object> oneCallable = new Tickets<Object>();
        FutureTask<Object> oneTask = new FutureTask<Object>(oneCallable);
 
        Thread t = new Thread(oneTask);
 
        System.out.println(Thread.currentThread().getName());
 
        t.start();
 
    }
 
}
 
class Tickets<Object> implements Callable<Object>{
 
    //重寫call方法
    @Override
    public Object call() throws Exception {
        // TODO Auto-generated method stub
        System.out.println(Thread.currentThread().getName()+"-->我是通過實現Callable接口通過FutureTask包裝器來實現的線程");
        return null;
    }   
}

程序運行結果: 
main 
Thread-0–>我是通過實現Callable接口通過FutureTask包裝器來實現的線程

線程實現方式4:通過線程池創建線程

public class ThreadDemo05{
 
    private static int POOL_NUM = 10;     //線程池數量
 
    /**
     * @param args
     * @throws InterruptedException 
     */
    public static void main(String[] args) throws InterruptedException {
        // TODO Auto-generated method stub
        ExecutorService executorService = Executors.newFixedThreadPool(5);  
        for(int i = 0; i<POOL_NUM; i++)  
        {  
            RunnableThread thread = new RunnableThread();
 
            //Thread.sleep(1000);
            executorService.execute(thread);  
        }
        //關閉線程池
        executorService.shutdown(); 
    }   
 
}
 
class RunnableThread implements Runnable  
{     
    @Override
    public void run()  
    {  
        System.out.println("通過線程池方式創建的線程:" + Thread.currentThread().getName() + " ");  
 
    }  
}  

程序運行結果: 
通過線程池方式創建的線程:pool-1-thread-3 
通過線程池方式創建的線程:pool-1-thread-4 
通過線程池方式創建的線程:pool-1-thread-1 
通過線程池方式創建的線程:pool-1-thread-5 
通過線程池方式創建的線程:pool-1-thread-2 
通過線程池方式創建的線程:pool-1-thread-5 
通過線程池方式創建的線程:pool-1-thread-1 
通過線程池方式創建的線程:pool-1-thread-4 
通過線程池方式創建的線程:pool-1-thread-3 
通過線程池方式創建的線程:pool-1-thread-2

ExecutorService、Callable都是屬於Executor框架。返回結果的線程是在JDK1.5中引入的新特徵,還有Future接口也是屬於這個框架,有了這種特徵得到返回值就很方便了。 
通過分析可以知道,他同樣也是實現了Callable接口,實現了Call方法,所以有返回值。這也就是正好符合了前面所說的兩種分類

執行Callable任務後,可以獲取一個Future的對象,在該對象上調用get就可以獲取到Callable任務返回的Object了。get方法是阻塞的,即:線程無返回結果,get方法會一直等待。

再介紹Executors類:提供了一系列工廠方法用於創建線程池,返回的線程池都實現了ExecutorService接口。

public static ExecutorService newFixedThreadPool(int nThreads) 
創建固定數目線程的線程池。
public static ExecutorService newCachedThreadPool() 
創建一個可緩存的線程池,調用execute 將重用以前構造的線程(如果線程可用)。如果現有線程沒有可用的,則創建一個新線程並添加到池中。終止並從緩存中移除那些已有 60 秒鐘未被使用的線程。
public static ExecutorService newSingleThreadExecutor() 
創建一個單線程化的Executor。
public static ScheduledExecutorService newScheduledThreadPool(int 
corePoolSize) 
創建一個支持定時及週期性的任務執行的線程池,多數情況下可用來替代Timer類。
ExecutoreService提供了submit()方法,傳遞一個Callable,或Runnable,返回Future。如果Executor後臺線程池還沒有完成Callable的計算,這調用返回Future對象的get()方法,會阻塞直到計算完成。

總結:


————————————————
版權聲明:本文爲CSDN博主「Mr_baci」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/java_zyq/article/details/87917734

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