1、繼承Thread類創建多線程:繼承java.lang.Thread類,重寫Thread類的run()方法,在run()方法中實現運行在線程上的代碼,調用start()方法開啟線程。
Thread 類本質上是實現了 Runnable 接口的一個實例,代表一個線程的實例。啟動線程的唯一方法就是通過 Thread 類的 start()實例方法。start()方法是一個 native 方法,它將啟動一個新線程,並執行 run()方法。
public class MyThread extends Thread { public void run() { System.out.println("MyThread.run()"); } } MyThread myThread1 = new MyThread(); myThread1.start();
2、實現Runable接口:實現java.lang.Runnable接口,重寫run()方法,在run()方法中實現運行在線程上的代碼。
如果自己的類已經 extends 另一個類,就無法直接 extends Thread,此時,可以實現一個Runnable 接口。
public class MyThread extends OtherClass implements Runnable { public void run() { System.out.println("MyThread.run()"); } }
//啟動 MyThread,需要首先實例化一個 Thread,並傳入自己的 MyThread 實例: MyThread myThread = new MyThread(); Thread thread = new Thread(myThread); thread.start(); //事實上,當傳入一個 Runnable target 參數給 Thread 后,Thread 的 run()方法就會調用 target.run() public void run() { if (target != null) { target.run(); } }
補充:兩種多線程方式比較:這兩種顯示的創建線程的方式,我們在實際編程中都不用,要用線程池進行統一的資源管理。
(1)Runable方法將線程同程序代碼、數據有效的分離,代碼相對整潔。
(2)避免java單繼承的局限性。一個已經繼承了某一個類的子類去創建線程,由於java子類不能繼承兩個父類,因此不能用Thread的方式,要使用實現Runnable接口的方式。
3、使用ExecutorService 、Callable<Class> 、Future 創建有返回值的線程
有返回值的任務必須實現 Callable 接口,類似的,無返回值的任務必須實現 Runnable 接口。執行Callable 任務后,可以獲取一個 Future 的對象,在該對象上調用 get 就可以獲取到 Callable 任務返回的 Object 了,再結合線程池接口 ExecutorService 就可以實現傳說中有返回結果的多線程了。
//創建一個線程池 ExecutorService pool = Executors.newFixedThreadPool(taskSize); // 創建多個有返回值的任務 List<Future> list = new ArrayList<Future>(); for (int i = 0; i < taskSize; i++) { Callable c = new MyCallable(i + " "); // 執行任務並獲取 Future 對象 Future f = pool.submit(c); list.add(f); } // 關閉線程池 pool.shutdown(); // 獲取所有並發任務的運行結果 for (Future f : list) { // 從 Future 對象上獲取任務的返回值,並輸出到控制台 System.out.println("res:" + f.get().toString()); }
4、基於線程池的方式
線程和數據庫連接這些資源都是非常寶貴的資源。那么每次需要的時候創建,不需要的時候銷毀,是非常浪費資源的。那么我們就可以使用緩存的策略,也就是使用線程池。
// 創建線程池 ExecutorService threadPool = Executors.newFixedThreadPool(10); while(true) { threadPool.execute(new Runnable() { // 提交多個線程任務,並執行 @Override public void run() { System.out.println(Thread.currentThread().getName() + " is running .."); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } } }); }