面试题之Runnable和Callable的区别
Posted 隐 风
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了面试题之Runnable和Callable的区别相关的知识,希望对你有一定的参考价值。
Runnable
Runnable接口非常简单,就定义了一个方法run(), 实现Runnable接口的run方法就可以实现多线程
// 函数式接口
@FunctionalInterface
public interface Runnable
public abstract void run();
Callable
很多人都知道要想在多线程中获取异步返回值结果一般是用Callable和FutureTask接口来配合实现,但可能很多人都不知道其实Callable是依赖于Runnable的run方法进行执行任务的,然后在通过FutureTask来收集返回值结果,下面咱们就自己模拟写一份FutureTask代码来看看是怎么实现的吧。
/**
* @author yinfeng
* @description 自己实现futureTask,基于park/unpark进行线程通讯
* @since 2022/1/9 21:32
*/
public class MyFutureTask<T> implements Runnable
Callable<T> callable;
/**
* callable执行结果
*/
T result;
/**
* task执行状态
*/
String state = "new";
/**
* 存储正在等待的消费者
*/
LinkedBlockingQueue<Thread> waiters = new LinkedBlockingQueue<>();
public MyFutureTask(Callable<T> callable)
this.callable = callable;
@Override
public void run()
try
result = callable.call();
catch (Exception e)
e.printStackTrace();
finally
state = "end";
// 任务执行完成后通过unpark通知消费者
System.out.println(Thread.currentThread().getName() + " 生产者执行结束,通知消费者");
while (true)
Thread waiter = waiters.poll();
if (waiter == null)
break;
LockSupport.unpark(waiter);
/**
* park / unpark
*/
public T get() throws Exception
Thread mainThread = Thread.currentThread();
// 塞入等待的集合中
waiters.add(mainThread);
// 判断状态
System.out.println(Thread.currentThread().getName() + " 消费者进入等待");
while (!"end".equals(state))
// 阻塞等待任务执行完成后通知
LockSupport.park(mainThread);
return result;
我们写个demo测试一下
/**
* @author yinfeng
* @description
* @since 2022/1/9 21:32
*/
public class FutureTaskTest
public static void main(String[] args) throws Exception
final MyFutureTask<String> futureTask = new MyFutureTask<>(() ->
Thread.sleep(5000);
return "任务完成888";
);
new Thread(futureTask).start();
final String result = futureTask.get();
System.out.println("结果:"+result);
// 控制台打印如下:
// main 消费者进入等待
// Thread-0 生产者执行结束,通知消费者
// 结果:任务完成888
可以看到我们的demo也是正常运行的,所以很关键的一点还是Callable是依赖于Runnable的run方法进行执行任务的
以上是关于面试题之Runnable和Callable的区别的主要内容,如果未能解决你的问题,请参考以下文章