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; }
相同点:
1.都是接口,都能够实现多线程编程,都需要Thread.start()来启动线程。
不同点:
1.Callable接口支持返回执行结果,此时需要调用FutureTask.get()方法实现,此方法会阻塞主线程直到获取‘将来’结果;当不调用此方法时,主线程不会阻塞!
Callable使用
/** * CallableImpl 简要描述 * <p> TODO:描述该类职责 </p> * * @author ckmike * @version 1.0 * @date 18-12-6 下午8:53 * @copyright ckmike **/ public class CallableImpl implements Callable<String> { private String accept; public CallableImpl(String accept) { this.accept = accept; } @Override public String call() throws Exception { // 休眠 TimeUnit.SECONDS.sleep(3); return this.accept; } public static void main(String[] args) throws ExecutionException, InterruptedException { Callable<String> callable = new CallableImpl("my callable test!"); FutureTask<String> task = new FutureTask<>(callable); long beginTime = System.currentTimeMillis(); // 创建线程 new Thread(task).start(); // 调用get()阻塞主线程,反之,线程不会阻塞 String result = task.get(); long endTime = System.currentTimeMillis(); System.out.println("hello : " + result); System.out.println("cast : " + (endTime - beginTime) / 1000 + " second!"); } }
Runnable使用
/** * RunnableImpl 简要描述 * <p> TODO:描述该类职责 </p> * * @author ckmike * @version 1.0 * @date 18-12-6 下午9:03 * @copyright ckmike **/ public class RunnableImpl implements Runnable { public RunnableImpl(String accept) { this.accept = accept; } private String accept; @Override public void run() { // 线程阻塞 1 秒,此时有异常产生,只能在方法内部消化,无法上抛 try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } // 最终处理结果无法返回 System.out.println("hello : " + this.accept); } public static void main(String[] args) { Runnable runnable = new RunnableImpl("my runable test!"); long beginTime = System.currentTimeMillis(); new Thread(runnable).start(); long endTime = System.currentTimeMillis(); System.out.println("cast : " + (endTime - beginTime) / 1000 + " second!"); } }
写这篇文章的原因是:面试时问道Runnable与Callable的区别,平时也就用Runnable比较多,基本上没有用过Callable,所以就挂了,哈哈哈,也总结给有需要的朋友。有知道Callable接口的使用场景吗?有的话可以留意分享给我吗?谢谢了!