詳解多線程啟動(dòng)涉及的知識點(diǎn)
Thread類
如果一個(gè)類繼承Thread,則不適合資源共享。但是如果實(shí)現(xiàn)了Runable接口的話,則很容易地實(shí)現(xiàn)資源共享。實(shí)現(xiàn)Runnable接口比繼承Thread類所具有的優(yōu)勢:
適合多個(gè)相同的程序代碼的線程去處理同一個(gè)資源
可以避免java中的單繼承的限制
增加程序的健壯性,代碼可以被多個(gè)線程共享,代碼和數(shù)據(jù)獨(dú)立
//繼承 ThreadThread1 mTh1=new Thread1("A");Thread1 mTh2=new Thread1("B");mTh1.start();mTh2.start();
Runnable接口
// 先看一下java.lang.Runnable,它是一個(gè)接口,在它里面只聲明了一個(gè)run()方法:// 由于run()方法返回值為void類型,所以在執(zhí)行完任務(wù)之后無法返回任何結(jié)果。public interface Runnable {public abstract void run();}//實(shí)現(xiàn)Runnable接口Thread2 mTh = new Thread2();new Thread(mTh, "C").start();//同一個(gè)mTh,但是在Thread中就不可以,如果用同一個(gè)實(shí)例化對象mt,就會(huì)出現(xiàn)異常new Thread(mTh, "D").start();new Thread(mTh, "E").start();
這兩種方式都有一個(gè)缺陷就是:在執(zhí)行完任務(wù)之后無法獲取執(zhí)行結(jié)果。如果需要獲取執(zhí)行結(jié)果,就必須通過共享變量或者使用線程通信的方式來達(dá)到效果,這樣使用起來就比較麻煩。
而自從Java 1.5開始,就提供了Callable和Future,通過它們可以在任務(wù)執(zhí)行完畢之后得到任務(wù)執(zhí)行結(jié)果。
Callable接口
Callable接口位于java.util.concurrent包下,在它里面也只聲明了一個(gè)方法,只不過這個(gè)方法叫做call()。
public interface Callable<V> {V call() throws Exception;}
可以看到,這是一個(gè)泛型接口,call()函數(shù)返回的類型就是傳遞進(jìn)來的V類型。Callable接口可以看作是Runnable接口的補(bǔ)充,call方法帶有返回值,并且可以拋出異常。
FutureTask類
如何獲取Callable的返回結(jié)果呢?一般是通過FutureTask這個(gè)中間媒介來實(shí)現(xiàn)的。整體的流程是這樣的:
把Callable實(shí)例當(dāng)作參數(shù),生成一個(gè)FutureTask的對象
然后把這個(gè)對象當(dāng)作一個(gè)Runnable,作為參數(shù)另起線程。

由于FutureTask實(shí)現(xiàn)了Runnable,因此它既可以通過Thread包裝來直接執(zhí)行,也可以提交給ExecuteService來執(zhí)行。下面以Thread包裝線程方式啟動(dòng)來說明一下。
import java.util.concurrent.Callable;import java.util.concurrent.FutureTask;public class Demo {public static void main(String[] args) throws Exception {Callable<Integer> call = new Callable<Integer>() {public Integer call() throws Exception {System.out.println("計(jì)算線程正在計(jì)算結(jié)果...");Thread.sleep(3000);return 1;}};FutureTask<Integer> task = new FutureTask<>(call);Thread thread = new Thread(task);thread.start();System.out.println("main線程干點(diǎn)別的...");Integer result = task.get();System.out.println("從計(jì)算線程拿到的結(jié)果為:" + result);}}
Future接口
FutureTask繼承體系中的核心接口是Future。
Future的核心思想是:一個(gè)方法,計(jì)算過程可能非常耗時(shí),等待方法返回,顯然不明智。可以在調(diào)用方法的時(shí)候,立馬返回一個(gè)Future,可以通過Future這個(gè)數(shù)據(jù)結(jié)構(gòu)去控制方法f的計(jì)算過程。這里的控制包括:
public interface Future<V> {boolean cancel(boolean mayInterruptIfRunning);//還沒計(jì)算完,可以取消計(jì)算過程boolean isCancelled();///判斷計(jì)算是否被取消boolean isDone();//判斷是否計(jì)算完V get() throws InterruptedException, ExecutionException;//獲取計(jì)算結(jié)果(如果還沒計(jì)算完,也是必須等待的)V get(long timeout, TimeUnit unit)throws InterruptedException, ExecutionException, TimeoutException;}
也就是說Future提供了三種功能:
判斷任務(wù)是否完成;
能夠中斷任務(wù);
能夠獲取任務(wù)執(zhí)行結(jié)果。
實(shí)現(xiàn)Runnable接口和Callable接口的區(qū)別
如果想讓線程池執(zhí)行任務(wù)的話需要實(shí)現(xiàn)的Runnable接口或Callable接口。
Runnable接口或Callable接口實(shí)現(xiàn)類都可以被ThreadPoolExecutor或ScheduledThreadPoolExecutor執(zhí)行。兩者的區(qū)別在于 Runnable 接口不會(huì)返回結(jié)果但是 Callable 接口可以返回結(jié)果。
備注:工具類 Executors 可以實(shí)現(xiàn) Runnable 對象和 Callable 對象之間的相互轉(zhuǎn)換。
Executors.callable(Runnable task)也就是說Future提供了三種功能:
判斷任務(wù)是否完成;
能夠中斷任務(wù);
能夠獲取任務(wù)執(zhí)行結(jié)果。
或Executors.callable(Runnable task,Object resule )。
記得點(diǎn)「贊」和「在看」↓
愛你們
