Java多線程實(shí)現(xiàn)方式主要有四種:繼承Thread類(lèi)灯抛、實(shí)現(xiàn)Runnable接口坑赡、實(shí)現(xiàn)Callable接口通過(guò)FutureTask包裝器來(lái)創(chuàng)建Thread線程嫉鲸、使用ExecutorService为牍、Callable馅精、Future實(shí)現(xiàn)有返回結(jié)果的多線程次慢。
其中前兩種方式線程執(zhí)行完后都沒(méi)有返回值旁涤,后兩種是帶返回值的。
Runnable和Callable的區(qū)別
Runnable接口
@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();
}
Callable接口
@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和Callable的區(qū)別
1.Runnable執(zhí)行方法是run(),Callable是call()
2.實(shí)現(xiàn)Runnable接口的任務(wù)線程無(wú)返回值迫像;實(shí)現(xiàn)Callable接口的任務(wù)線程能返回執(zhí)行結(jié)果
3.call方法可以拋出異常劈愚,run方法若有異常只能在內(nèi)部消化
注意
Callable接口支持返回執(zhí)行結(jié)果,需要調(diào)用FutureTask.get()方法實(shí)現(xiàn)闻妓,此方法會(huì)阻塞主線程直到獲取結(jié)果菌羽;當(dāng)不調(diào)用此方法時(shí),主線程不會(huì)阻塞由缆!
如果線程出現(xiàn)異常注祖,F(xiàn)uture.get()會(huì)拋出throws InterruptedException或者ExecutionException;如果線程已經(jīng)取消均唉,會(huì)爬出CancellationException
Callable示例
package com.keda.activiti.config;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
/**
* @program: xxx
* @description:
* @author: shuonar
* @create: 2020-06-02 16:52
**/
public class ExecutorsTest {
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(2);
Callable<String> callable = new Callable<String>() {
@Override
public String call() throws Exception {
Thread.sleep(3000);
System.out.println("Thread_current="+Thread.currentThread());
return "Hello World!";
}
};
System.out.println("start thread ....");
Future<String> future = executorService.submit(callable);
try {
System.out.println("future.get()=" + future.get());
}catch (Exception e){
e.printStackTrace();
}
System.out.println("end thread...");
// 切記:關(guān)閉線程池
executorService.shutdown();
}
}
start thread ....
Thread_current=Thread[pool-1-thread-1,5,main]
future.get()=Hello World!
end thread...
其它
在程序開(kāi)發(fā)中只要是多線程肯定永遠(yuǎn)以實(shí)現(xiàn)Runnable接口為主是晨,因?yàn)閷?shí)現(xiàn)Runnable接口相比繼承Thread類(lèi)有如下好處:
1.避免點(diǎn)繼承的局限,一個(gè)類(lèi)可以實(shí)現(xiàn)多個(gè)接口
2.資源共享
Runnable接口和Thread之間的聯(lián)系
public class Thread extends Object implements Runnable
由此可見(jiàn):Thread類(lèi)也是Runnable接口的子類(lèi)