第一種:extend Threadjava
第二種:implement Runnable多線程
第三種:Executors.newFixedThreadPool(int n).execute(...)測試
第一種(繼承)、第二種(實現接口)是所有版本jdk一直支持,第三種(線程池)jdk1.5纔開始出現。this
/*第一種 1.自定義類繼承Thread 2.自定義類複寫run方法 3.實例化自定義類,調用start方法(做用是啓動線程並調用複寫的run方法) */ class Demo extend Thread{ public void run(){...} } class T{ public static void main(String[] args){ new Demo().start(); //線程1 new Demo().start(); //線程2 new Demo().start(); //線程3 } }
/*第二種【經常使用】 1.自定義類實現Runnable接口 2.自定義類複寫run方法 3.實例化自定義類,把自定義類的實例做爲參數實例化Thread類(可實例化多個,就是所謂的多線程),而後調用start方法 */ class Demo implement Runnable{ public void run(){...} } class T{ public static void main(String[] args){ Demo demo = new Demo(); new Thead(demo).start(); //線程1 new Thead(demo).start(); //線程2 new Thead(demo).start(); //線程3 } }
第一種和第二種方法其實同樣,主要是由於java的單繼承機制纔出現了第二種【經常使用】方法。線程
//第三種 //簡易版 import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class Test{ public static void main(String[] args){ ExecutorService pool = Executors.newFixedThreadPool(3); //建立線程池,容量爲3 for(int i=0;i<10;i++) { pool.execute(new Runnable(){public void run(){ System.out.println();}}); } Executors.newCachedThreadPool().execute(new Runnable(){public void run(){}}); Executors.newSingleThreadExecutor().execute(new Runnable(){public void run(){}}); } } //詳細版(可運行進行測試) import java.util.concurrent.*; import java.util.Date; import java.util.List; import java.util.ArrayList; public class Test { public static void main(String[] args) throws ExecutionException, InterruptedException { System.out.println("----程序開始運行----"); Date date1 = new Date(); int taskSize = 5; // 建立一個可重用固定線程數的線程池,以共享的無界隊列方式來運行這些線程。 ExecutorService pool = Executors.newFixedThreadPool(taskSize); // 用於存聽任務返回值 List<Future> list = new ArrayList<Future>(); for (int i = 0; i < taskSize; i++) { Callable c = new MyCallable(i + " "); // 執行任務並獲取Future對象 //pool提交一個返回值的任務用於執行,返回一個表示任務的未決結果的Future。 Future f = pool.submit(c); // System.out.println(">>>" + f.get().toString()); list.add(f); } // 關閉線程池 pool.shutdown(); // 遍歷全部線程的返回值 for (Future f : list) { System.out.println(">>>" + f.get().toString()); } Date date2 = new Date(); System.out.println("----程序結束運行----,程序運行時間【" + (date2.getTime() - date1.getTime()) + "毫秒】"); } } //有返回值實現Callable,無返回值實現Runnable class MyCallable implements Callable<Object> { private String taskNum; MyCallable(String taskNum) { this.taskNum = taskNum; } //實現Callable必須實現call方法 //計算結果,若是沒法計算結果,則拋出一個異常。 public Object call() throws Exception { System.out.println(">>>" + taskNum + "任務啓動"); Date dateTmp1 = new Date(); Thread.sleep(1000); Date dateTmp2 = new Date(); long time = dateTmp2.getTime() - dateTmp1.getTime(); System.out.println(">>>" + taskNum + "任務終止"); return taskNum + "任務返回運行結果,當前任務時間【" + time + "毫秒】"; } }
個人理解:code
由Executors.newFixedThreadPool(int n)定義一個能夠執行必定數量線程的線程池,pool.submit(c)把須要執行的任務扔進(提交到)線程池進行執行,這樣就能夠不阻塞得同時執行多個任務(即所謂的多線程)。對象
Callable和Runnable同樣是接口,二者的區別是Callable執行完call()後返回一個Object,Runnable執行完run()後不返回。call()和run()功能相同(除了有無返回值的區別)。繼承
Future是一個類型(也就是類啦),用來裝Callable執行完call()後返回的Object(其實這裏返回的是Object,爲啥不能用Object來裝,非要用Future來裝呢?我也不明白,可是API說須要用這個裝就用唄)。接口
因爲是多線程,每一個線程都執行完都有返回,因此須要用一個容器(即集合)——ArrayList<Future>來裝。隊列
線程池的方法能夠獲取任務執行的返回值(這些返回值可能有用),另外,此方法也能夠執行submit(T<? implement Runnable>)無返回值的方法。
so,我以爲第三種通吃,直接用第三種方式得了。