Java 杂谈扣丁学堂Java培训

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

2018-08-13  本文已影响2人  994d14631d16

  今天扣丁学堂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来跟踪异步计算的结果。

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

上一篇下一篇

猜你喜欢

热点阅读