java里面創建線程有四種方式,這四種方式可以通過是否有返回值進行區分:
1.創建任務,實現Runnable接口,重寫run();
2.繼承Thread類,重寫run();
1.實現Callable接口,重寫call(),利用FutureTask包裝Callable,并作為task傳入Thread構造函數;
2.使用線程池。
首先我們來看下線程之間的狀態,及他們之間的相互轉換:
實現Runnable接口
因為Java只支持單繼承,繼承了Thread類就不能再繼承別的類了,所以實現繼承更推薦讓線程類實現Runnable接口。將Runnbale作為參數傳入Thread的構造函數,創建Thread。
繼承Thread類,重寫run()
創建線程只需要繼承Thread類,然后在run()方法里寫下線程要實現的任務即可;通過調用start方法來啟動線程,但不能直接調用run()方法。
①Thread類本質上是實現了Runnable接口,代表一個線程的實例。
②Runnable接口只有一個抽象的run()方法。
③啟動線程的唯一方法就是通過Thread類的start()方法。
④start()方法是一個native方法,它將啟動一個新的線程,并執行run()方法。
⑤自定義類直接繼承Thread,并重寫run()方法,就可以啟動新線程并執行自己定義的run()方法。
利用Callable接口創建并啟動
①定義MyClass實現Callable接口;
②重寫call(),將執行的代碼邏輯植入;
③創建FutureTask的對象;FutureTask中定義了run(),run()內部調用了call(),并保存了call()的返回值;
FutureTaskfuturetask=newFutureTask(newMyClass());
④創建Thread的對象;
Threadthread=newThread(futuretask);//傳入參數Runnable接口
⑤啟動線程;thread.start();
⑥可通過FutureTask類的get()方法獲得線程執行結束后的返回值,即call的返回值。futuretask.get();
通過線程池來創建線程
①newThreadPoolExecutor(…);
②創建任務TaskimplementsCallable,重寫run()方法;
③通過線程池的execute()或submit()將任務command傳入線程池;
④獲取返回值。
示例代碼如下:
總結
線程的創建有四種方式:主要分為有返回和無返回,具體根據使用場景來選擇。
①如果不需要返回且線程數量小,則建議采用實現Runnable接口,重寫run()的方式;
②如果需要返回且線程數量小,則建議采用實現Callable接口,重寫call(),利用FutureTask包裝成一個Runnable,再作為參數傳入Thread的構造方法的方式創建線程;
③如果線程數量較多,則建議采用線程池方式創建:execute提交任務實現無返回操作,submit提交任務實現有返回操作。