Runnable
Runnable接口非常简单,就定义了一个方法run(), 实现Runnable接口的run方法就可以实现多线程
// 函数式接口@FunctionalInterfacepublicinterfaceRunnable{publicabstractvoidrun();}
Callable
可能很多人都知道要想在多线程中获取异步返回值结果一般是用Callable和FutureTask接口来实现,但可能很多人都不知道其实Callable是依赖于Runnable的run方法进行执行任务的,然后在通过FutureTask来收集返回值结果,下面咱们就自己模拟写一份FutureTask代码来看看是怎么实现的吧。
/**
* @author yinfeng
* @description 自己实现futureTask,基于park/unpark进行线程通讯
* @since 2022/1/9 21:32
*/publicclassMyFutureTask<T>implementsRunnable{
Callable<T> callable;/**
* callable执行结果
*/
T result;/**
* task执行状态
*/
String state ="new";/**
* 存储正在等待的消费者
*/
LinkedBlockingQueue<Thread> waiters =newLinkedBlockingQueue<>();publicTonyFutureTask(Callable<T> callable){this.callable = callable;}@Overridepublicvoidrun(){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
*/publicclassFutureTaskTest{publicstaticvoidmain(String[] args)throws Exception {final MyFutureTask<String> futureTask =newMyFutureTask<>(()->{
Thread.sleep(5000);return"任务完成888";});newThread(futureTask).start();final String result = futureTask.get();
System.out.println("结果:"+result);// 控制台打印如下: // main 消费者进入等待// Thread-0 生产者执行结束,通知消费者// 结果:任务完成888}}
可以看到我们的demo也是正常运行的,所以很关键的一点还是Callable是依赖于Runnable的run方法进行执行任务的
版权归原作者 隐 风 所有, 如有侵权,请联系我们删除。