Java多線程之Callable接口的實現(xiàn)
1.接口的定義:
public interface Callable<V>
{
V call() throws Exception;
}
2.Callable和Runnable的異同
先看下Runnable接口的定義
public interface Runnable {
public abstract void run();
}
Callable的call()方法類似于Runnable接口中run()方法,都定義任務(wù)要完成的工作,實現(xiàn)這兩個接口時要分別重寫這兩個方法,主要的不同之處是call()方法是有返回值的(其實還有一些區(qū)別,例如call方法可以拋出異常,run方法不可以),運行Callable任務(wù)可以拿到一個Future對象,表示異步計算的結(jié)果。它提供了檢查計算是否完成的方法,以等待計算的完成,并檢索計算的結(jié)果。通過Future對象可以了解任務(wù)執(zhí)行情況,可取消任務(wù)的執(zhí)行,還可獲取執(zhí)行結(jié)果。
3. Callable類型的任務(wù)可以有兩種執(zhí)行方式:
我們先定義一個Callable任務(wù)MyCallableTask:
class MyCallableTask implements Callable<Integer>{
@Override
public Integer call() throws Exception {
System.out.println("線程在進行計算");
Thread.sleep(3000);
int sum = 0;
for(int i=0;i<100;i++)
sum += i;
return sum;
}
}
①借助FutureTask執(zhí)行
FutureTask類同時實現(xiàn)了兩個接口,F(xiàn)uture和Runnable接口,所以它既可以作為Runnable被線程執(zhí)行,又可以作為Future得到Callable的返回值。
借助FutureTask執(zhí)行的大體流程是:
Callable<Integer> mycallabletask = new MyCallableTask(); FutureTask<Integer> futuretask= new FutureTask<Integer>(mycallabletask); new Thread(futuretask).start();
通過futuretask可以得到MyCallableTask的call()的運行結(jié)果: futuretask.get();
②借助線程池來運行
線程池中執(zhí)行Callable任務(wù)的原型例如:
public interface ExecutorService extends Executor {
//提交一個Callable任務(wù),返回值為一個Future類型
<T> Future<T> submit(Callable<T> task);
//other methods...
}
借助線程池來運行Callable任務(wù)的一般流程為:
ExecutorService exec = Executors.newCachedThreadPool(); Future<Integer> future = exec.submit(new MyCallableTask());
通過future可以得到MyCallableTask的call()的運行結(jié)果: future.get();
在網(wǎng)上看到了幾個比較好的代碼例子:
a.Callable任務(wù)借助FutureTask運行:
public class CallableAndFutureTask {
public static void main(String[] args) {
Callable<Integer> callable = new Callable<Integer>() {
public Integer call() throws Exception {
return new Random().nextInt(100);
}
};
FutureTask<Integer> future = new FutureTask<Integer>(callable);
new Thread(future).start();
try {
Thread.sleep(5000);
System.out.println(future.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
b.Callable任務(wù)和線程池一起使用,然后返回值是Future:
public class CallableAndFuture {
public static void main(String[] args) {
ExecutorService threadPool = Executors.newSingleThreadExecutor();
Future<Integer> future = threadPool.submit(new Callable<Integer>() {
public Integer call() throws Exception {
return new Random().nextInt(100);
}
});
try {
Thread.sleep(5000);// 可能做一些事情
System.out.println(future.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
c.當(dāng)執(zhí)行多個Callable任務(wù),有多個返回值時,我們可以創(chuàng)建一個Future的集合,例如:
class MyCallableTask implements Callable<String> {
private int id;
public OneTask(int id){
this.id = id;
}
@Override
public String call() throws Exception {
for(int i = 0;i<5;i++){
System.out.println("Thread"+ id);
Thread.sleep(1000);
}
return "Result of callable: "+id;
}
}
public class Test {
public static void main(String[] args) {
//Callable<String> mycallabletask = new MyCallableTask(1);
ExecutorService exec = Executors.newCachedThreadPool();
ArrayList<Future<String>> results = new ArrayList<Future<String>>();
for (int i = 0; i < 5; i++) {
results.add(exec.submit(new MyCallableTask(i)));
}
for (Future<String> fs : results) {
if (fs.isDone()) {
try {
System.out.println(fs.get());
} catch (Exception e) {
e.printStackTrace();
}
} else {
System.out.println("MyCallableTask任務(wù)未完成!");
}
}
exec.shutdown();
}
}
那么引入Callable接口具有哪些好處呢?
①可以獲得任務(wù)執(zhí)行返回值;
②通過與Future的結(jié)合,可以實現(xiàn)利用Future來跟蹤異步計算的結(jié)果。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
springboot整合mybatis-plus 實現(xiàn)分頁查詢功能
這篇文章主要介紹了springboot整合mybatis-plus 實現(xiàn)分頁查詢功能,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-09-09
使用Jenkins自動化構(gòu)建工具進行敏捷開發(fā)
這篇文章主要為大家介紹了使用Jenkins自動化構(gòu)建工具進行敏捷開發(fā),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步早日升職加薪2022-04-04
Java不借助第三變量實現(xiàn)兩數(shù)交換的示例
本文主要介紹了Java不借助第三變量實現(xiàn)兩數(shù)交換的示例,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-02-02
Java線性結(jié)構(gòu)中棧、隊列和串的基本概念和特點詳解
前幾天小編給大家介紹了Java線性結(jié)構(gòu)中的鏈表,除了鏈表這種結(jié)構(gòu)之外,實際上還有棧、隊列、串等結(jié)構(gòu),那么這些結(jié)構(gòu)又有哪些特點呢,本文就給大家詳細的介紹一下,感興趣的小伙伴跟著小編一起來看看吧2023-07-07
詳解Spring注解@Autowired的實現(xiàn)原理和使用方法
在使用Spring開發(fā)的時候,配置的方式主要有兩種,一種是xml的方式,另外一種是 java config的方式,在使用的過程中,我們使用最多的注解應(yīng)該就是@Autowired注解了,所以本文就給大家講講@Autowired注解是如何使用和實現(xiàn)的,需要的朋友可以參考下2023-07-07
Mybatis中的PageHelper的執(zhí)行流程分析
這篇文章主要介紹了Mybatis的PageHelper執(zhí)行流程,本文給大家介紹介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-02-02

