一:繼承Thread類建立線程異步
1:繼承Thread類定義線程子類;函數
2:重寫run()方法,定義線程的操做;this
3:經過建立的線程子類對象.start() 啓動線程。spa
package com.thread; public class FirstThreadTest extends Thread{ public void run() { System.out.println(Thread.currentThread().getName()); } public static void main(String[] args) { new FirstThreadTest().start(); } }
二:實現Runnable接口建立線程線程
1:實現Runnable接口定義線程類;對象
2:重寫run()方法;繼承
3:建立Thread對象:把上面 實現runnable接口的線程類 的對象做爲構造參數,建立出線程對象;接口
4:由thread對象的start()方法啓動線程;資源
public class RunnableThreadTest implements Runnable { public void run() { System.out.println(Thread.currentThread().getName()) } public static void main(String[] args) { new Thread(new RunnableThreadTest()).start(); } }
三:經過Callable接口和Future建立線程get
1:建立Callable接口的實現類,並指明返回值類型;
2:在實現類中重寫call()方法,並返回結果;
3:建立Future<V>類型的list接收線程的預期結果: List<Future<String>> results = new ArrayList<Future<String>>();
4:經過線程池啓動線程,而且把線程返回結果add到list中;
5:遍歷list時,經過每一個元素的 get() 方法獲取每一個線程的實際運行結果值;
//實現callable接口,定義線程類 class TaskWithResult implements Callable<String>{ private int id; public TaskWithResult(int id){ this.id = id; } //重寫call()方法,切記拋出異常,並返回值 public String call() throws Exception { return "result of task:" + id; }
public class TestCallable { public static void main(String[] args) { //建立線程池 ExecutorService es = Executors.newCachedThreadPool(); //建立預期結果集合 List<Future<String>> results = new ArrayList<Future<String>>(); for(int i=0;i<5;i++){ //經過線程池啓動線程,把線程結果保存到預期結果集合 results.add(es.submit(new TaskWithResult(i))); } //遍歷結果集合 for(Future<String> fs : results){ try { //經過 結果.get() 方法獲取每一個線程運行結束後的返回值。並處理異常 System.out.println(fs.get()); } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); } } } }
另外一種啓動callable實現類線程的辦法:
Callable<Result> ca = new Callable<Result>() { public Result call() throws Exception { System.out.println("當前線程名稱是:" + Thread.currentThread().getName()); Thread.sleep(2000L); return new Result("callable 執行完畢"); } }; //包裝對象 FutureTask<Result> ft = new FutureTask<Result>(ca); try { //啓動線程執行 new Thread(ft).start(); //獲取結果 System.out.println(ft.get().getMsg()); } catch (Exception e) { e.printStackTrace(); } }
四:對比
1:繼承Thread類建立線程:其run()方法沒有返回值;經過start方法啓動;因爲Java不能容許多繼承,一個類若是須要繼承其餘類就不能再定義爲線程類了;run方法中的異常必須捕獲並處理;
2:實現runnable接口建立線程:其run()方法沒有返回值;經過做爲thread類的構造函數的參數被包裝成thread類對象,再經過start方法啓動(由此,能夠同一個任務對象交給多個thread對象來運行,實現資源的共享以及並行處理);因爲接口能夠多實現,一個類能夠繼承其餘類的同時實現runnable接口成爲線程類;run方法中的異常必須捕獲並處理;
3:實現Callable接口建立線程:其call()方法有返回值;通常經過線程池來啓動線程,也能夠先包裝成爲FutureTask對象,而後再由futuretask對象包裝成Thread對象經過start方法啓動;call()方法能夠拋出異常,直到在結果處經過get()方法獲取結果時再處理異常;在主線程啓動實現callable建立的線程時能夠得到一個Future對象做爲異步處理的預期結果,在經過future.get()方法時檢測啓動的線程是否已完成並返回結果,是則獲得結果,不然阻塞主線程等待任務線程完成並返回結果;