java面试常问的Runnable和Callable的区别

作者:隐 时间:2023-11-23 09:23:28 

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方法进行执行任务的

来源:https://blog.csdn.net/a1774381324/article/details/121578160

标签:Java,Runnable,Callable
0
投稿

猜你喜欢

  • 一篇文章带你了解Java Spring基础与IOC

    2021-07-06 07:54:49
  • Java Mybatis框架多表操作与注解开发详解分析

    2023-12-04 17:15:14
  • Android计时器控件Chronometer应用实例

    2023-03-01 09:46:59
  • 详解Java程序读取properties配置文件的方法

    2022-03-09 17:26:23
  • Java线程之守护线程(Daemon)用法实例

    2023-11-29 09:15:13
  • Spring超详细讲解创建BeanDefinition流程

    2023-11-25 08:37:55
  • 基于WPF实现筛选下拉多选控件

    2021-11-15 20:47:50
  • 浅谈C# StringBuilder内存碎片对性能的影响

    2023-12-15 08:55:47
  • Android使用Matrix旋转图片模拟碟片加载过程

    2022-08-22 21:07:32
  • 利用Android两行代码真正杀死你的App

    2023-04-07 17:15:46
  • 解决C# X64应用程序中读取WParam溢出的问题

    2022-01-22 17:41:03
  • Android编程简单实现雷达扫描效果

    2021-06-17 20:38:04
  • android手机获取gps和基站的经纬度地址实现代码

    2022-04-05 03:03:00
  • Android 中通过实现线程更新Progressdialog (对话进度条)

    2023-04-16 14:57:50
  • IDEA调试技巧条件断点实现步骤详解

    2023-11-24 16:02:42
  • mybatis中insert主键ID获取和多参数传递的示例代码

    2023-09-20 07:11:00
  • c# 快速排序算法

    2021-10-18 07:33:20
  • Spring Boot Debug调试过程图解

    2023-12-13 10:27:33
  • C#实现更改MDI窗体背景颜色的方法

    2021-07-01 13:06:16
  • Android实现上拉加载更多以及下拉刷新功能(ListView)

    2022-03-02 15:50:41
  • asp之家 软件编程 m.aspxhome.com