線程的三種啟動方式
- X extends Thread ;然后X.run
2.X implements Runnable; 然后有Thread 來運(yùn)行
3.X implements Callable; 然后有Thread 來運(yùn)行
第一種繼承子Thread 類
public class ThreadExtends extends Thread{
@Override
public void run() {
super.run();
System.out.println("測試數(shù)據(jù)");
}
}
啟動方式:
ThreadExtends threadExtends = new ThreadExtends();
threadExtends.start();
第二種方式
實(shí)現(xiàn)Runnable
接口
public class ThreadRunnable implements Runnable {
@Override
public void run() {
String name = Thread.currentThread().getName();
System.out.println("測試Runnable currentThread"+name);
}
}
啟動方式:
new Thread(new ThreadRunnable()).start();
第三種 實(shí)現(xiàn)Callable<V>
接口,這種方式帶有返回值的
import java.util.concurrent.Callable;
public class ThreadCall implements Callable<String> {
@Override
public String call() throws Exception {
System.out.println("callable =======");
return "測試";
}
}
啟動方式:
ThreadCall call = new ThreadCall();
FutureTask<String> futureTask = new FutureTask<>(call);
new Thread(futureTask).start();
String s = futureTask.get();
System.out.println(s);
輸出:
實(shí)現(xiàn)Callable 接口的結(jié)果展示
以上三種方式拟枚,第 1,2 中方式運(yùn)行完成以后無法獲取運(yùn)行的結(jié)果哗魂, 從JDK1.5 開始就提供了Callable
和Future
,通過他們可以獲取線程運(yùn)行完成后的結(jié)果.
Callabel
只是聲明了一個接口斥滤,有個call()
的方法烂琴,只是一個泛型接口弧械,call()
函數(shù)返回的類型就是傳進(jìn)來的類型.
//只是一個接口
@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;
}
Future
就是對具體的Runnable
和Callable
任務(wù)的執(zhí)行結(jié)果進(jìn)行取消、查詢和是否完成譬挚、獲取結(jié)果锅铅。
必要時用get()
方法獲取執(zhí)行結(jié)果,但是該方法會阻塞到任務(wù)結(jié)束返回結(jié)果减宣。
因?yàn)?code>Future 是一個接口狠角,無法直接用來從創(chuàng)建對象的,因此就有了FutureTask
蚪腋。
public class FutureTask<V> implements RunnableFuture<V>
package java.util.concurrent;
/**
* A {@link Future} that is {@link Runnable}. Successful execution of
* the {@code run} method causes completion of the {@code Future}
* and allows access to its results.
* @see FutureTask
* @see Executor
* @since 1.6
* @author Doug Lea
* @param <V> The result type returned by this Future's {@code get} method
*/
public interface RunnableFuture<V> extends Runnable, Future<V> {
/**
* Sets this Future to the result of its computation
* unless it has been cancelled.
*/
void run();
}
FutureTask
實(shí)現(xiàn)了RunnableFuture
接口丰歌,RunnableFuture
接口集成了Runnable
接口和Future
接口,所以它皆可以作為Runnable
被線程執(zhí)行屉凯,有可以作為Future
得到Callable
得到返回值立帖。事實(shí)上FutureTask
是Future
的唯一實(shí)現(xiàn)類。要new 一個FutureTask 有兩個方法:
FutureTask 可參考上文的實(shí)現(xiàn)方式悠砚。
中止
- 線程自然中止:要么是run 執(zhí)行完畢了晓勇,要么就是出現(xiàn)異常被迫停止了。
- 手動中止:已經(jīng)被廢棄的方式就不提了灌旧,現(xiàn)在基本不用了绑咱。被廢棄原因是會造成死鎖,程序運(yùn)行在不穩(wěn)定狀態(tài)下枢泰。
- 安全中止:則是其他線程調(diào)用當(dāng)前線程的
interrupt()
方法對其進(jìn)行一個中斷操作描融,線程則通過isInterrupt()
來判斷是否中止,也可以調(diào)用Thread.isInterrupt()
來判斷當(dāng)前線程是否被中止衡蚂。
不提倡用自定義的標(biāo)記來進(jìn)行中斷
因?yàn)榫€程運(yùn)行是不規(guī)則的窿克,你需要斷開的,但是沒有斷開毛甲,這時候程序就會出現(xiàn)運(yùn)行問題年叮。