一. 實(shí)現(xiàn) Runnable 接口敌买,并實(shí)現(xiàn)該接口的 run() 方法媒殉。
主要步驟:
- 自定義類并實(shí)現(xiàn) Runnable 接口什黑,實(shí)現(xiàn) run() 方法碧库。
- 創(chuàng)建 Thread 對(duì)象盅粪,用實(shí)現(xiàn) Runnable 接口的對(duì)象作為參數(shù)實(shí)例化該 Thread 對(duì)象钓葫。
- 調(diào)用 Thread 的 start 方法。
class MyThread implements Runnable {
// create my own Thread class
public void run() {
System.out.println("Thread body");
}
}
public class Test {
public static void main(String[] args) {
MyThread thread = new MyThread();
Thread t = new Thread(thread);
t.start(); //start the thread
}
}
二. 繼承 Thread 類票顾,重寫(xiě) run 方法瓤逼。
Thread是實(shí)現(xiàn)了 Runnable 接口的一個(gè)實(shí)例,它代表了一個(gè)線程的實(shí)例库物,并且啟動(dòng)線程的唯一方法就是通過(guò) Thread 類的 start()方法霸旗。start()方法是一個(gè) native(本地)方法,它將啟動(dòng)一個(gè)新線程戚揭,并執(zhí)行 run()方法(Thread 中提供的 run()方法是一個(gè)空方法)诱告。注意,當(dāng) start()方法調(diào)用后并不是立即執(zhí)行多線程代碼民晒,而是使該線程變?yōu)榭蛇\(yùn)行態(tài)(Runnable),什么時(shí)候運(yùn)行多線程代碼是由操作系統(tǒng)決定的精居。
class MyThreadB extends Thread {
public void run() {
System.out.println("Thread body");
}
}
public class Test {
public static void main(String[] args) {
MyThreadB thread = new MyThreadB();
thread.start();
}
}
三. 實(shí)現(xiàn) Callable接口,重寫(xiě) call()方法潜必。
靴姿。
Callable 對(duì)象實(shí)際屬于 Executor 框架中的功能類,Callable 接口與 Runnable 接口類似磁滚,但提供了更強(qiáng)大的功能佛吓,包括以下三點(diǎn):**
- Callable 可以在任務(wù)結(jié)束后提供一個(gè)返回值,Runnable無(wú)法提供此功能垂攘。
- Callable中的 call()方法可以拋出異常维雇,而 Runnable的 run()方法不能拋異常。
- 運(yùn)行 Callable 可以拿到一個(gè) Future 對(duì)象晒他,F(xiàn)uture 對(duì)象表示異步計(jì)算的結(jié)果吱型。它提供了檢查計(jì)算是否完成的方法。由于線程屬于異步計(jì)算模型陨仅,所以無(wú)法從其他線程中得到方法的返回值津滞,在這種情況下铝侵,就可以使用 Future 來(lái)監(jiān)視目標(biāo)線程調(diào)用 call()方法的情況,當(dāng)調(diào)用 Future 的 get()方法以獲取結(jié)果時(shí)触徐,當(dāng)前線程就會(huì)阻塞咪鲜,直到 call()方法結(jié)束返回結(jié)果。
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
/**
* Created by qd on 12/5/17.
*/
public class CallableAndFuture {
public static class CallableTest implements Callable<String> {
public String call() throws Exception {
return "Hello World!";
}
}
public static void main(String[] args) {
ExecutorService threadPool = Executors.newSingleThreadExecutor();
Future<String> future = threadPool.submit(new CallableTest());
try {
System.out.println("waiting thread to finish");
System.out.println(future.get()); //等待線程結(jié)束,并獲取返回結(jié)果
} catch (Exception e) {
e.printStackTrace();
}
}
}
當(dāng)需要實(shí)現(xiàn)多線程的時(shí)候锌介,一般推薦實(shí)現(xiàn) Runnable 接口的方式,原因如下:首先猾警,Thread 類定義了多種方法可以被派生類使用或重寫(xiě)孔祸,但是只有 run 方法是必須被重寫(xiě)的,在 run 方法中實(shí)現(xiàn)這個(gè)線程的主要功能发皿。這當(dāng)然是實(shí)現(xiàn) Runnable 接口所需的同樣的方法崔慧。而且,很多 java 開(kāi)發(fā)人員認(rèn)為穴墅,一個(gè) 類僅在它們需要被加強(qiáng)或被修改時(shí)才會(huì)被繼承惶室。因此,如果沒(méi)有必要重新 Thread 類的其他方法玄货,那么通過(guò)繼承 Thread 的實(shí)現(xiàn)方式與實(shí)現(xiàn) Runnable 接口的效果相同皇钞,在這種情況下最好通過(guò)實(shí)現(xiàn) Runnable 接口的方式來(lái)創(chuàng)建線程。