人物背景:老徐,男,本名徐富贵,从事Java相关研发多年,职场老手,青年专家。钓鱼。徐。据说他之前因为炒某币而输光了所有家产,现在还负债累累。阿珍,女,本名陈家珍,是一名刚入职的实习生。虽然是职场新人,但她聪明好学。据说她是校内四大美女之一,追求者从旺角排到铜锣湾,但至今仍单身。阿珍探出头看着老徐的屏幕,全是绿色的图形,好奇地问:“老徐,你在看什么?”,尴尬地笑道:“我只是看看最新的行情。”老徐立马把窗户关了。阿震不以为然,继续问道:“我总是把Runnable和Callable这两个接口搞混,有什么区别?”面对阿震的灵魂拷问,老徐平静地说:“Runnable是用来提供多个线程任务支持的核心接口,Callable是Java1.5中加入的Runnable的改进版本。”“在说它们的区别之前,我们先分别了解一下这两个接口。”老徐边说边打开源码:Runnable接口@FunctionalInterfacepublicinterfaceRunnable{publicabstractvoidrun();}Runnable接口是一个函数式接口,只有一个run()方法,不接受任何参数,做不返回任何值。由于方法签名未指定throws子句,因此无法进一步传播已检查的异常。适用于我们不使用线程执行结果的情况,比如异步打印日志:记录器=记录器工厂。getLogger(LoggingTask.class);私有字符串名称;publicLoggingTask(Stringname){this.name=name;}@Overridepublicvoidrun(){logger.info("{}said:Hello!",this.name);}}上面的例子中,信息是根据name参数记录在日志文件中的,没有返回值。我们可以通过Thread来启动,例如:publicstaticvoidmain(String[]args){Stringname="万茂学院";线程thread=newThread(newLoggingTask(name));thread.start();;}我们也可以通过ExecutorService启动,例如:publicstaticvoidmain(String[]args){Stringname="万茂学院";ExecutorServiceexecutorService=Executors.newSingleThreadExecutor();executorService.execute(新的LoggingTask(名称));executorService.shutdown();}Callableinterface@FunctionalInterfacepublicinterfaceCallable{Vcall()throwsException;}Callable接口也是一个函数式接口,它只有一个call()方法,不接受任何参数,返回一个通用的ValueV,在方法签名上包含一个throwsException子句,因此我们可以轻松地进一步传播已检查的异常。适用于我们使用线程来执行结果的情况,比如异步计算阶乘:publicFactorialTask??(intn){this.n=n;}@OverridepublicIntegercall()throwsIllegalArgumentException{intfact=1;if(n<0){thrownewIllegalArgumentException("必须大于或等于零");}for(inti=n;i>1;i--){fact=fact*i;}返回事实;}}在上面的例子中,根据n参数计算它的阶乘,并返回计算结果。我们只能通过ExecutorService启动,例如:publicstaticvoidmain(String[]args)throwsExecutionException,InterruptedException{Futurefuture=executorService.submit(newFactorialTask??(5));System.out.println(future.get());executorService.shutdown();}call()方法的结果可以通过Future对象获取,如果在调用Future对象的get()方法时出现call()方法,如果发现异常,则异常会被传递,如:publicstaticvoidmain(String[]args)throwsExecutionException,InterruptedException{ExecutorServiceexecutorService=Executors.newSingleThreadExecutor();Futurefuture=executorService.submit(newFactorialTask??(-1));System.out.println(future.get());executorService.shutdown();}抛出如下异常:老徐回头看了看阿珍说:“你知道这次不一样!”阿珍愣愣的说:“信息量有点大,能不能你帮我总结一下?”“当然。”老徐答道。总结一下Runnable和Callable的区别:Callable任务执行后可以返回值,而Runnable任务不能返回值。Callable只能由ExecutorService启动,Runnable可以由Thread和ExecutorService启动。Callable的call()方法可以传播已检查的异常,但Runnable的run()方法不能。最后,谢谢你这么帅,给我点赞和关注。