java面试常问的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方法进行执行任务的

到此这篇关于java面试常问的Runnable和Callable的区别的文章就介绍到这了,更多相关java Runnable和Callable区别内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Java中的Runnable,Callable,Future,FutureTask的比较

    Java中的Runnable,Callable,Future,FutureTask的比较 Java中存在Runnable.Callable.Future.FutureTask这几个与线程相关的类或者接口,在Java中也是比较重要的几个概念,我们通过下面的简单示例来了解一下它们的作用于区别. Runnable 其中Runnable应该是我们最熟悉的接口,它只有一个run()函数,用于将耗时操作写在其中, 该函数没有返回值 .然后使用某个线程去执行该runnable即可实现多线程,Thread类在调

  • Java 线程对比(Thread,Runnable,Callable)实例详解

    Java 线程对比Thread,Runnable,Callable java 使用 Thread 类代表线程,所有现场对象都必须是 Thread 类或者其子类的实例.每个线程的作用是完成一定的任务,实际上就是执行一段程序流.java 使用线程执行体来代表这段程序流. 1.继承Thread 类创建线程 启动多线程的步骤如下: (1)定义Thread 类的子类,并重写该类的run() 方法,该run() 方法的方法体就代表类线程需要完成的任务.因此把run() 方法称为线程执行体. (2)创建 Th

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

    Runnable Runnable接口非常简单,就定义了一个方法run(), 实现Runnable接口的run方法就可以实现多线程 // 函数式接口 @FunctionalInterface public interface Runnable { public abstract void run(); } Callable 可能很多人都知道要想在多线程中获取异步返回值结果一般是用Callable和FutureTask接口来实现,但可能很多人都不知道其实Callable是依赖于Runnable的r

  • java锁synchronized面试常问总结

    目录 synchronized都问啥? synchronized是什么? synchronized锁什么? synchronized怎么用? 结语 synchronized都问啥? 如果Java面试有什么是必问的,synchronized必定占据一席之地.初出茅庐时synchronized的用法,成长后synchronized的原理,可谓是Java工程师的“一生之敌”. 按照惯例,先来看synchronized的常见问题(在线Excel同步更新中): 根据统计数据可以总结出synchronize

  • Java初学者常问的问题(推荐)

    本文介绍一些Java初学者常问的问题,可以用%除以一个小数吗? a += b 和 a = a + b 的效果有区别吗? 声明一个数组为什么需要花费大量时间? 为什么Java库不用随机pivot方式的快速排序? 基本数据类型 Q. 为什么 -0/3 结果是 0,而 -0.0/3.0 结果是 -0.0?(注意后边的结果0带负号) A. 在Java里,整数是用补码表示的.在补码中0只有一种表示方法.另一方面,浮点数则是用 IEEE 标准表示的, 对于0有两种表示方法, 0 和 -0. Q. 我可以用

  • 面试官:怎么做JDK8的垃圾收集器的调优(面试常问)

    看着面试官真诚的眼神,心中暗想看起来年纪轻轻却提出如此直击灵魂的问题.擦了擦额头上汗,我稍微调整了一下紧张的情绪,对面试官说: 在JDK8中有Serial收集器.Parallel收集器.CMS收集器.G1收集器这么几种收集器,需要根据实际硬件配置和业务需求进行选择调优. 如此浅显的回答,无法让面试官达到深入的要求,肯定不能满足面试官强烈的需求,果不其然面试官又追问到:如果是桌面应用,内存占用也就100MB,应该选择哪种垃圾收集器呢?我快速的回答:Serial收集器.看着面试官期待的眼神,我又详细

  • Java面试必问之ThreadLocal终极篇分享

    目录 前言 ThreadLocal是什么 ThreadLoalMap hash冲突 内存泄露 如何避免内存泄露 总结 前言 在面试环节中,考察"ThreadLocal"也是面试官的家常便饭,所以对它理解透彻,是非常有必要的. 有些面试官会开门见山的提问: "知道ThreadLocal吗?" "讲讲你对ThreadLocal的理解" 当然了,也有面试官会慢慢引导到这个话题上,比如提问"在多线程环境下,如何防止自己的变量被其它线程篡改&qu

  • Web面试常问回流reflow与重绘repaint原理及区别

    目录 浏览器的渲染机制 回流 与 重绘 回流 导致回流的操作: 重绘 导致重绘的操作: 浏览器的渲染机制 1.浏览器采用两个引擎来处理页面的工作, 不同的浏览器使用的渲染引擎不一样 渲染引擎: Chrom和Safari使用"WebKit", Firefor使用"Geoko" js引擎 2.浏览器会把html解析成 DOM树, 把css解析成 CSSOM(CSS对象模型); 3.接着会把 DOM树 和 CSSOM, 结合产生 render tree(渲染树); 4.渲

  • Java面试岗常见问题之ArrayList和LinkedList的区别

    目录 1.ArrayList和LinkedList是什么? 2.ArrayList和LinkedList性能比较 1.插入效率比较 2.查询效率比较 3.删除效率比较 4.实验总结 3.面试标准回答 1.ArrayList和LinkedList是什么? 在我看来,要想搞清楚ArrayList和LinkedList有什么区别,首先一定得要知道这两个东西到底是什么.因为在我看来,通常拿来被比较有区别的东西,它们大体上一定存在很多相似的地方.为了剖析本质,我们直接看看它们的源码声明. Arraylis

  • 面试常问:如何保证Redis缓存和数据库的数据一致性

    目录 一.一致性 1.强一致性 2.弱一致性 3.最终一致性 二.redis缓存和mysql数据库数据一致性解决 1.方案一:采用延时双删策略 2.方案二:一步更新缓存(基于订阅Binlog的同步机制) 首先,我们先来看看有哪几种一致性的情况呢? 一.一致性 1.强一致性 如果你的项目对缓存的要求是强一致性的,那么请不要使用缓存.这种一致性级别是最符合用户直觉的,它要求系统写入什么,读出来的也会是什么,用户体验好,但实现起来往往对系统的性能影响大. 2.弱一致性 这种一致性级别约束了系统在写入成

  • java面试突击之sleep和wait有什么区别详析

    目录 前言 区别一:语法使用不同 区别二:所属类不同 区别三:唤醒方式不同 区别四:释放锁资源不同 sleep不释放锁 wait释放锁 区别五:线程进入状态不同 总结 前言 sleep 方法和 wait 方法都是用来将线程进入休眠状态的,并且 sleep 和 wait 方法都可以响应 interrupt 中断,也就是线程在休眠的过程中,如果收到中断信号,都可以进行响应,并抛出 InterruptedException 异常.那 sleep 和 wait 的区别都有哪些呢?接下来,我们一起来看.

  • 10个Python面试常问的问题(小结)

    概述 Python是个非常受欢迎的编程语言,随着近些年机器学习.云计算等技术的发展,Python的职位需求越来越高.下面我收集了10个Python面试官经常问的问题,供大家参考学习. 类继承 有如下的一段代码: class A(object): def show(self): print 'base show' class B(A): def show(self): print 'derived show' obj = B() obj.show() 如何调用类A的show方法了. 方法如下: o

随机推荐