Java Thread的基礎實踐方法
文章目的
讓讀者了解Java Thread的方法,目前Java Thread有三種實踐方法如下
- 實作Runnable介面
- 實作Callable介面
- 繼承Thread類別
實作Runnable
Runnable是甚麼?
Runnable是一個介面提供一個run方法,原始程式碼如下
原始碼
@FunctionalInterface
public interface Runnable {
/**
* When an object implementing interface <code>Runnable</code> is used
* to create a thread, starting the thread causes the object's
* <code>run</code> method to be called in that separately executing
* thread.
* <p>
* The general contract of the method <code>run</code> is that it may
* take any action whatsoever.
*
* @see java.lang.Thread#run()
*/
public abstract void run();
}
原始碼要點
- @FunctinalInerface annotation是標明此介面可以透過Java8 lambda的方式去實踐
- run方法沒有回傳值,代表執行後無法接收解果
實踐方法
實作runnable中的run方法,在傳入thread的建構者創建新的thread,並且執行run
public class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println("Hi my name is Monster Lee");
}
public static void main(String[] args) {
Thread thread = new Thread(new MyRunnable());
thread.run();
}
}
實作Callable
甚麼是Callable?
Callable如同Runnable是一個需要實作的介面,而他與Runnable最大的差別在於,主程式呼叫後可以接取此執行緒的回傳值。接下來透過Java的原始碼來講解
原始碼
@FunctionalInterface
public interface Callable<V> {
/**
* Computes a result, or throws an exception if unable to do so.
*
* @return computed result
* @throws Exception if unable to compute a result
*/
V call() throws Exception;
}
原始碼要點
- 如同Runnable有@FunctionalInterface代表可以透過Lambda去實踐
- 和Runnable不同的地方再與,他提供了V template並且在call時回傳這個template,代表在call結束時會回傳定義Callable template的物件
- 所以Runnable和Callable的最大差異在於,執行後始否可以回傳值
實踐方法
實作Callable中的call方法,並且在宣告template時定義要回傳的物件,(範例為String),在要呼叫Callable的主程式中先定義FutureTask及回傳的template物件,並且將寫好的Callable傳入建構者中,Callable需要依靠FutureTask來接收回傳值,最後再新增一個Thread去跑此FutereTask,如果需要取回回傳值則直接呼叫FuterTask中的get方法及可以接收。
public class MyCallable implements Callable<String> {
@Override
public String call() throws Exception {
return "Hi my name is Monster Lee";
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
MyCallable mc = new MyCallable();
FutureTask<String> ftData = new FutureTask<>(mc);
Thread thread = new Thread(ftData);
thread.run();
System.out.println(ftData.get());
}
}
繼承Thread
Thread是甚麼?
Thread是Java執行緒操作的基本,若要執行的話則直接呼叫start方法
原始碼
public synchronized void start() {
/**
* This method is not invoked for the main method thread or "system"
* group threads created/set up by the VM. Any new functionality added
* to this method in the future may have to also be added to the VM.
*
* A zero status value corresponds to state "NEW".
*/
if (threadStatus != 0)
throw new IllegalThreadStateException();
/* Notify the group that this thread is about to be started
* so that it can be added to the group's list of threads
* and the group's unstarted count can be decremented. */
group.add(this);
boolean started = false;
try {
start0();
started = true;
} finally {
try {
if (!started) {
group.threadStartFailed(this);
}
} catch (Throwable ignore) {
/* do nothing. If start0 threw a Throwable then
it will be passed up the call stack */
}
}
}
private native void start0();
原始碼要點
- Thread我們可以看到基本的start方法的實踐,主要透過呼叫start0這個方法,**而第33行的start0的前贅字native是Java用來呼叫C或C 語言的方法,簡單來說就是Java告訴OS我要呼叫一個start0我不知道是C或C++實踐你只要給我呼叫就好。*
實踐方法
繼承Thread Class並且改寫run方法,在主程序中執行start()方法
public class MyThread extends Thread {
@Override
public void run() {
System.out.println("Hi my name is Monster Lee");
}
public static void main(String[] args) {
MyThread mt = new MyThread();
mt.start();
}
}
總結
整篇文章主要介紹了
- 實作Runnable介面
- 實作Callable介面
- 繼承Thread類別
而三種不同的實踐執行緒主要差別如下
- 如果需要handle回傳值的話使用Callable
- Runnable和Thread的差別主要在於
- 實作介面和繼承Class
- 這代表了實作介面的Runnable會比繼承Thread來的彈性(因為實作可以多從實作並且可以從中間改變行為,而繼承則只能硬生生地繼承Thread(連不必要的方法都須一覽接下)
留言
張貼留言