美文网首页Java 杂谈扣丁学堂Java培训
扣丁学堂Java开发多线程之实现Callable接口代码示例

扣丁学堂Java开发多线程之实现Callable接口代码示例

作者: 994d14631d16 | 来源:发表于2018-08-13 15:31 被阅读2次

      今天扣丁学堂Java培训老师给大家介绍一下关于Java开发多线程之Callable接口的实现,Callable和Runnbale一样代表着任务,区别在于Callable有返回值并且可以抛出异常,下面我们一起来看一下吧。

    ​  1.接口的定义:

      publicinterfaceCallable

      {

      Vcall()throwsException;

      }

      2.Callable和Runnable的异同

      先看下Runnable接口的定义

      publicinterfaceRunnable{

      publicabstractvoidrun();

      }

      Callable的call()方法类似于Runnable接口中run()方法,都定义任务要完成的工作,实现这两个接口时要分别重写这两个方法,主要的不同之处是call()方法是有返回值的(其实还有一些区别,例如call方法可以抛出异常,run方法不可以),运行Callable任务可以拿到一个Future对象,表示异步计算的结果。它提供了检查计算是否完成的方法,以等待计算的完成,并检索计算的结果。通过Future对象可以了解任务执行情况,可取消任务的执行,还可获取执行结果。

      3.Callable类型的任务可以有两种执行方式:

      我们先定义一个Callable任务MyCallableTask:

      classMyCallableTaskimplementsCallable{

      @Override

      publicIntegercall()throwsException{

      System.out.println("线程在进行计算");

      Thread.sleep(3000);

      intsum=0;

      for(inti=0;i<100;i++)

      sum+=i;

      returnsum;

      }

      }

      ①借助FutureTask执行

      FutureTask类同时实现了两个接口,Future和Runnable接口,所以它既可以作为Runnable被线程执行,又可以作为Future得到Callable的返回值。

      借助FutureTask执行的大体流程是:

      Callablemycallabletask=newMyCallableTask();

      FutureTaskfuturetask=newFutureTask(mycallabletask);

      newThread(futuretask).start();

      通过futuretask可以得到MyCallableTask的call()的运行结果:futuretask.get();

      ②借助线程池来运行

      线程池中执行Callable任务的原型例如:

      publicinterfaceExecutorServiceextendsExecutor{

      //提交一个Callable任务,返回值为一个Future类型

      Futuresubmit(Callabletask);

      //othermethods...

      }

      借助线程池来运行Callable任务的一般流程为:

      ExecutorServiceexec=Executors.newCachedThreadPool();

      Futurefuture=exec.submit(newMyCallableTask());

      通过future可以得到MyCallableTask的call()的运行结果:future.get();

      在网上看到了几个比较好的代码例子:

      a.Callable任务借助FutureTask运行:

      publicclassCallableAndFutureTask{

      publicstaticvoidmain(String[]args){

      Callablecallable=newCallable(){

      publicIntegercall()throwsException{

      returnnewRandom().nextInt(100);

      }

      };

      FutureTaskfuture=newFutureTask(callable);

      newThread(future).start();

      try{

      Thread.sleep(5000);

      System.out.println(future.get());

      }catch(InterruptedExceptione){

      e.printStackTrace();

      }catch(ExecutionExceptione){

      e.printStackTrace();

      }

      }

      }

      b.Callable任务和线程池一起使用,然后返回值是Future:

      publicclassCallableAndFuture{

      publicstaticvoidmain(String[]args){

      ExecutorServicethreadPool=Executors.newSingleThreadExecutor();

      Futurefuture=threadPool.submit(newCallable(){

      publicIntegercall()throwsException{

      returnnewRandom().nextInt(100);

      }

      });

      try{

      Thread.sleep(5000);//可能做一些事情

      System.out.println(future.get());

      }catch(InterruptedExceptione){

      e.printStackTrace();

      }catch(ExecutionExceptione){

      e.printStackTrace();

      }

      }

      }

      c.当执行多个Callable任务,有多个返回值时,我们可以创建一个Future的集合,例如:

      classMyCallableTaskimplementsCallable{

      privateintid;

      publicOneTask(intid){

      this.id=id;

      }

      @Override

      publicStringcall()throwsException{

      for(inti=0;i<5;i++){

      System.out.println("Thread"+id);

      Thread.sleep(1000);

      }

      return"Resultofcallable:"+id;

      }

      }

      publicclassTest{

      publicstaticvoidmain(String[]args){

      //Callablemycallabletask=newMyCallableTask(1);

      ExecutorServiceexec=Executors.newCachedThreadPool();

      ArrayList>results=newArrayList>();

      for(inti=0;i<5;i++){

      results.add(exec.submit(newMyCallableTask(i)));

      }

      for(Futurefs:results){

      if(fs.isDone()){

      try{

      System.out.println(fs.get());

      }catch(Exceptione){

      e.printStackTrace();

      }

      }else{

      System.out.println("MyCallableTask任务未完成!");

      }

      }

      exec.shutdown();

      }

      }

      那么引入Callable接口具有哪些好处呢?

      ①可以获得任务执行返回值;

      ②通过与Future的结合,可以实现利用Future来跟踪异步计算的结果。

      以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持扣丁学堂。

    相关文章

      网友评论

        本文标题:扣丁学堂Java开发多线程之实现Callable接口代码示例

        本文链接:https://www.haomeiwen.com/subject/dorubftx.html