Callable和Runnable很像,都是可以创建线程,但是他俩也是有很大的区别的
1.Runnable位于java.lang包下,Callable位于java.util.concurrent包下
2.
Runnable接口中的方法
@FunctionalInterface public interface Runnable { /** * When an object implementing interface <code>Runnable</code> is used * to create a thread, starting the thread causes the object's * <code>run</code> method to be called in that separately executing * thread. * <p> * The general contract of the method <code>run</code> is that it may * take any action whatsoever. * * @see java.lang.Thread#run() */ public abstract void run(); }
Callable接口中的方法
@FunctionalInterface public interface Callable<V> { /** * Computes a result, or throws an exception if unable to do so. * * @return computed result * @throws Exception if unable to compute a result */ V call() throws Exception; }
3.从上面的方法结果中可以看出
1.Call()方法是有返回值的,run()方法没有
2.call()方法可以抛出异常,而run()方法不能抛出异常
Callable的第一种使用方法
package com.yjc.juc; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.FutureTask; public class MyCallable implements Callable<String> { @Override public String call() throws Exception { System.out.println("执行call()"); return "callable"; } public static void main(String[] args) throws ExecutionException, InterruptedException { MyCallable myCallable=new MyCallable(); //利用FutureTask执行Callable并且接受结果 FutureTask<String> stringFutureTask = new FutureTask<String>(myCallable); //利用线程执行Task任务 new Thread(stringFutureTask).start(); //接受结果FutureTask.get会发生阻塞情况 System.out.println("接受的返回值为:"+stringFutureTask.get()); System.out.println("MyCallable执行完毕,返回值结果正确接收"); } }
使用线程池的方式执行call()
package com.yjc.juc; import java.util.concurrent.*; public class MyCallable implements Callable<String> { @Override public String call() throws Exception { System.out.println("执行call()"); return "callable"; } public static void main(String[] args) throws ExecutionException, InterruptedException { MyCallable myCallable=new MyCallable(); //创建一个线程池 ExecutorService executorService = Executors.newFixedThreadPool(3); //创建线程执行任务,接受任务结果 Future<String> future = executorService.submit(myCallable); //接受返回值 System.out.println(future.get()); System.out.println("方式二,线程池:MyCallable执行完毕,返回值结果正确接收~"); //停止线程池 executorService.shutdown(); }
注意点,同一个对象的call()方法,即使多个线程调用也只会执行一遍
public static void main(String[] args) throws ExecutionException, InterruptedException { MyCallable myCallable=new MyCallable(); //利用FutureTask执行Callable并且接受结果 FutureTask<String> stringFutureTask = new FutureTask<String>(myCallable); //利用线程执行Task任务 new Thread(stringFutureTask).start(); new Thread(stringFutureTask).start(); //接受结果FutureTask.get会发生阻塞情况 System.out.println("接受的返回值为:"+stringFutureTask.get()); System.out.println("MyCallable执行完毕,返回值结果正确接收"); }
Future的常用方法
Future.get()方法获取任务执行结果,该方法如果没有返回时,暂时处于阻塞状态
Future.get(Long timeOut,TimeUnit timeUnit)可以设置超时时间
Future.boolean isDone()如果线程结束,无论是正常结束还是任务终止都会返回true
Future.boolean isCanceller()如果任务完成前被取消则返回true
Future.boolean cancel(boolean flag),方法参数如果传入为true代表中断任务,如果任务中断成功,则返回值为true,如果失败则为false