今天就跟大家聊聊有關(guān)怎么在Java中利用多線程實(shí)現(xiàn)一個Callable接口,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結(jié)了以下內(nèi)容,希望大家根據(jù)這篇文章可以有所收獲。
成都創(chuàng)新互聯(lián)公司是一家集成都網(wǎng)站建設(shè)、成都網(wǎng)站制作、網(wǎng)站頁面設(shè)計(jì)、網(wǎng)站優(yōu)化SEO優(yōu)化為一體的專業(yè)的建站公司,已為成都等多地近百家企業(yè)提供網(wǎng)站建設(shè)服務(wù)。追求良好的瀏覽體驗(yàn),以探求精品塑造與理念升華,設(shè)計(jì)最適合用戶的網(wǎng)站頁面。 合作只是第一步,服務(wù)才是根本,我們始終堅(jiān)持講誠信,負(fù)責(zé)任的原則,為您進(jìn)行細(xì)心、貼心、認(rèn)真的服務(wù),與眾多客戶在蓬勃發(fā)展的市場環(huán)境中,互促共生。
1.接口的定義:
public interface Callable{ V call() throws Exception; }
2.Callable和Runnable的異同
先看下Runnable接口的定義
public interface Runnable { public abstract void run(); }
Callable的call()方法類似于Runnable接口中run()方法,都定義任務(wù)要完成的工作,實(shí)現(xiàn)這兩個接口時要分別重寫這兩個方法,主要的不同之處是call()方法是有返回值的(其實(shí)還有一些區(qū)別,例如call方法可以拋出異常,run方法不可以),運(yùn)行Callable任務(wù)可以拿到一個Future對象,表示異步計(jì)算的結(jié)果。它提供了檢查計(jì)算是否完成的方法,以等待計(jì)算的完成,并檢索計(jì)算的結(jié)果。通過Future對象可以了解任務(wù)執(zhí)行情況,可取消任務(wù)的執(zhí)行,還可獲取執(zhí)行結(jié)果。
3. Callable類型的任務(wù)可以有兩種執(zhí)行方式:
我們先定義一個Callable任務(wù)MyCallableTask:
class MyCallableTask implements Callable{ @Override public Integer call() throws Exception { System.out.println("線程在進(jìn)行計(jì)算"); Thread.sleep(3000); int sum = 0; for(int i=0;i<100;i++) sum += i; return sum; } }
①借助FutureTask執(zhí)行
FutureTask類同時實(shí)現(xiàn)了兩個接口,F(xiàn)uture和Runnable接口,所以它既可以作為Runnable被線程執(zhí)行,又可以作為Future得到Callable的返回值。
借助FutureTask執(zhí)行的大體流程是:
Callablemycallabletask = new MyCallableTask(); FutureTask futuretask= new FutureTask (mycallabletask); new Thread(futuretask).start();
通過futuretask可以得到MyCallableTask的call()的運(yùn)行結(jié)果: futuretask.get();
②借助線程池來運(yùn)行
線程池中執(zhí)行Callable任務(wù)的原型例如:
public interface ExecutorService extends Executor { //提交一個Callable任務(wù),返回值為一個Future類型Future submit(Callable task); //other methods... }
借助線程池來運(yùn)行Callable任務(wù)的一般流程為:
ExecutorService exec = Executors.newCachedThreadPool(); Futurefuture = exec.submit(new MyCallableTask());
通過future可以得到MyCallableTask的call()的運(yùn)行結(jié)果: future.get();
在網(wǎng)上看到了幾個比較好的代碼例子:
a.Callable任務(wù)借助FutureTask運(yùn)行:
public class CallableAndFutureTask { public static void main(String[] args) { Callablecallable = new Callable () { public Integer call() throws Exception { return new Random().nextInt(100); } }; FutureTask future = new FutureTask (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(); Futurefuture = threadPool.submit(new Callable () { 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{ 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 mycallabletask = new MyCallableTask(1); ExecutorService exec = Executors.newCachedThreadPool(); ArrayList > results = new ArrayList >(); for (int i = 0; i < 5; i++) { results.add(exec.submit(new MyCallableTask(i))); } for (Future 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é)合,可以實(shí)現(xiàn)利用Future來跟蹤異步計(jì)算的結(jié)果。
看完上述內(nèi)容,你們對怎么在Java中利用多線程實(shí)現(xiàn)一個Callable接口有進(jìn)一步的了解嗎?如果還想了解更多知識或者相關(guān)內(nèi)容,請關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝大家的支持。