多线程面试_3_多线程在运行过程中抛出异常回调函数-程序员宅基地

技术标签: 面试  多线程  

如何给run()方法传参

我们都知道,跟线程相关的业务逻辑都是要放在run()方法里去执行的,而run()方法是没有参数也没有返回值的,那么应该如何给run()方法传参呢?

  1. 构造函数传参: 这就是我上一篇博客里利用Runnable接口实现多线程的例子.
  2. 成员变量传参: 这个就比如我在run()方法里使用了一个全局变量,我们通过给全局变量赋值然后在run方法中使用该值,就起到了传参的效果,就是我上一篇博客Thread实现多线程的例子.
  3. 回调函数传参: 我jio的就是在run()方法里去调用其他方法并获取其返回值加以使用的意思.

如何实现处理线程的返回值

我们有的程序的执行依赖于子任务的返回值进行的,当子任务通过线程去执行的时候,是需要获取其返回值的,这可咋整?实现子线程返回值的方法是啥?

  1. 主线程等待法,即我们可以让主线程循环等待,直到目标子线程返回了其结果为止,这种方法实现起来比较简单,但是需要自己实现循环等待的逻辑,以及我们不知道要等待多久,需要等待的变量一多,代码就会很臃肿.
public class MainThreadWait implements Runnable{

    private String value;

    @Override
    public void run() {
        try {
            Thread.currentThread().sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("running");
        value = "we have data now";
    }

    public static void main(String[] args) throws InterruptedException {
        MainThreadWait mtw = new MainThreadWait();
        Thread t1 = new Thread(mtw);

        t1.start();
        //直接执行main方法,还是会出现value为空的现象,因为主线程没有等它赋值结束就执行了打印语句,此时我们就需要让主线程一直等着
        while (mtw.value == null) {
            System.out.println("waiting...");
            Thread.currentThread().sleep(100);
        }
        //有了上面的代码之后,我们会发现,主线程会等待500毫秒直到value有值之后才会执行这条语句
        System.out.println(mtw.value);
    }
}
  1. 利用Thread类的join()方法来阻塞当前线程以等待子线程处理完毕.
    其中,join()的作用就是无限期阻塞当前线程,等待调用join()方法的线程对象被销毁再执行其他线程
public class MainThreadWait implements Runnable{

    private String value;

    @Override
    public void run() {
        try {
            Thread.currentThread().sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("running");
        value = "we have data now";
    }

    public static void main(String[] args) throws InterruptedException {
        MainThreadWait mtw = new MainThreadWait();
        Thread t1 = new Thread(mtw);

        t1.start();
        //阻塞当前线程等待t1线程执行结束
        t1.join();
        //有了上面的代码之后,我们会发现,主线程会等待500毫秒直到value有值之后才会执行这条语句
        System.out.println(mtw.value);
    }
}
  1. 通过Callable接口实现:通过FutureTask这个类或者线程池获取返回值

实现了Callable接口的任务可以有返回值,并且可以抛出异常,run()方法都不可以.
在执行Callable任务之后,可以获取一个Future接口对象,然后通过get方法就可以获取Callable任务返回的Object对象了.
通过Callable方式获取线程的返回值主要有两种方式: 通过FutureTask这个Future接口的实现类或者线程池获取.

---创建MyCallable类
public class MyCallable implements Callable<String> {
    @Override
    public String call() throws Exception {
        String value = "test";
        System.out.println("ready to work");
        //让当前线程休眠1秒
        Thread.currentThread().sleep(1000);
        System.out.println("task done");
        return value;
    }
}

---FutureTask方式测试类
public class MyCallable_FutureTask {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        FutureTask<String> task = new FutureTask<String>(new MyCallable());
        //因为Future接口继承了Runnable接口,而Thread可以通过Ruannable创建线程,所以这里可以穿task.
        Thread thread = new Thread(task);
        thread.start();

        //如果还没有执行结束
        if (!task.isDone()) {
            System.out.println("task has not finished, please wait");
        }
        //5秒之后,才会执行这句话
        System.out.println("task return : " + task.get());
    }
}
输出结果如图:

在这里插入图片描述

我们直接利用一下上面的Callable类
public static void main(String[] args) {
        //线程池创建好之后,就往线程池提交任务去让它执行,此处的任务就是我们的Callable
        ExecutorService newCacheThreadPool = Executors.newCachedThreadPool();
        Future<String> future = newCacheThreadPool.submit(new MyCallable());
        if (!future.isDone()) {
            System.out.println("task has not finished, please wait");
        }
        try {
            System.out.println(future.get());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        } finally {
            //关闭线程池
            newCacheThreadPool.shutdown();
        }
    }
    输出结果和上面的一样的.

使用线程池获取结果的好处就是我们可以提交多个实现Callable接口的类去让线程池并发(可以理解为多个线程同时进行) 的处理结果,其他的方法都是线性的,按照代码的顺序执行对应的线程.

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_41223155/article/details/98208650

智能推荐

我的网工奋斗经历-程序员宅基地

文章浏览阅读77次。本文来自:[url]http://bbs.51cto.com/thread-2520-1-1.html[/url] 经过三个月的奋斗,终于等到了这一天“11.5”。带着一颗沉重的心到来考场,也许我是所有考生第一个来到考场。9点的考试,我7点多就来了考场,一直到考场外徘徊着。等了差不多一个小时,看到了监考老师带着试卷来了,考生也一个接一个地来到考场。心跳加快,也不是紧张,就是一..._一个网工的故事

全国计算机金奖,长理学子在全国计算机系统与程序设计竞赛中获金奖-程序员宅基地

文章浏览阅读146次。新湖南客户端10月27日讯 (通讯员 喻玲 记者 胡泽汇)2018CCF大学生计算机系统与程序设计竞赛(CCSP)及颁奖会10月25-26日在杭州成功举办。本次竞赛由中国计算机学会(CCF)主办,杭州电子科技大学承办,是全国计算机最高水平的大学生竞赛,来自清华大学、复旦大学、上海交大、武汉大学、华中科技大学等全国62所高校的474名大学生计算机高手同场竞技,进行了实力对决。长沙理工大学在此次竞赛中..._中学生全国计算机程序设计竞赛奖励

追随大数据Hadoop的脚步-1-入门与背景(含视频资料与代码)_hadoop grep脚步-程序员宅基地

文章浏览阅读290次。title: 大数据Hadoop-1tags:hadoopcategories:technicalhadooptoc: truedeclare: truedate: 2020-11-06 13:35:43一、大数据基本背景1.1 大数据架构:1.2 企业数据部门的大数据工作流程:构建环境背景知识:服务器、磁盘、交换机、局域网、机架IDC(Internet Data Center)互联网数据中心磁盘阵列Radi廉价冗余磁盘阵列:将小容量磁盘整合为大磁盘充分利._hadoop grep脚步

C++string类常用方法_c++ string类的常用方法-程序员宅基地

文章浏览阅读9.1w次,点赞485次,收藏3.4k次。C++string类常用方法1、string(const char *s) :将 string 对象初始化为 s 指向的字符串string str("hello");2、string(size_type n,char c) :创建一个包含 n 个元素的 string 对象,其中每个元素都被初始化为字符 cstring str(10, 'a');3、string(const string &str) :将一个 string 对象初始化为 string 对象 str(复制构造函数)str_c++ string类的常用方法

BP(Back Propagation)神经网络学习笔记_sigmoid型激活函数使得bp网络的输出及其导数呈现如下图形-程序员宅基地

文章浏览阅读6.2w次,点赞88次,收藏415次。BP神经网络算法是在BP神经网络现有算法的基础上提出的,是通过任意选定一组权值,将给定的目标输出直接作为线性方程的代数和来建立线性方程组,解得待求权,不存在传统方法的局部极小及收敛速度慢的问题,且更易理解。_sigmoid型激活函数使得bp网络的输出及其导数呈现如下图形

android中无限循环滑动的gallery实例_android 自定义无限滑动的imageview-程序员宅基地

文章浏览阅读321次。1.点击图片有变暗的效果,使用imageview.setAlpha(),并且添加ontouchListener 1 public void init() { 2 dots = new ImageView[len]; 3 for (int j = 0; j ) { 4 // 添加图片 5 final _android 自定义无限滑动的imageview

随便推点

ZXCLOUD R5300 G3的服务器安装ESXI6.7镜像前篇-制作ESXI6.7定制版-程序员宅基地

文章浏览阅读684次。VMware vSphere Hypervisor (ESXi) Offline Bundle(脱机捆绑包)镜像。服务器安装版本与平时安装版本有所不同,由于服务器缺少阵列卡驱动,需将阵列卡驱动注入。注意:将镜像刻录到U盘时写入方式为USB-HDD+ V2或USB-ZIP+ V2。文件放入文件夹中,在文件夹中再创建一个文件夹,将。定制版镜像,阵列卡驱动完成注入!最新版(自己下载,以上所需文件。在“文件”选项中打开刚才生成的。下载自己去淘宝买一次性下载)文件,选中解除锁定,并应用。注意:下载镜像时需下载。_esxi6.7镜像

前端适配方案flexible.js-程序员宅基地

文章浏览阅读326次。flexible适配步骤_flexible.js

c语言单个字符输入问题_c语言输入字符-程序员宅基地

文章浏览阅读1.9k次,点赞6次,收藏5次。而在我们输入时,其实输入了两个数据,一个是‘A’,另一个是‘\n’,而scanf在遇到(空格,换行等)停止读取数据,而‘\n’就被下一次的scanf给读走了;但是如果是一次输入多个字符的情况,当我们在屏幕上输入一个字符时,不能像输入整型那样输入一个空格再输入下一个字符,这样会将空格当成一个字符赋给下一个变量,直接输入两个字符就行(情况1)① scanf正常运行时,返回值是它读取的变量的个数,如果输入错误或停止,会返回EOF,EOF的值为-1。整型的输入:格式符相邻,输入时中间可以加上空格或回车。_c语言输入字符

浪潮服务器U盘安装系统无法识别到电脑硬盘问题的解决_there is no sata device-程序员宅基地

文章浏览阅读2.6w次,点赞2次,收藏44次。浪潮服务器U盘安装系统无法识别到电脑硬盘问题的解决首先说明一下,我是开发人员,不是专业的运维。公司来了一台服务器要我给他装linux系统,我呢就按正常的U盘安装系统方法操作,结果在选择安装位置指定磁盘的时候,发现只有我插入的那张U盘别检测到,服务器有一张1T的硬盘却没有被检测到。于是找了很多方法都没用,最终在联系厂家,在他们专家的指导下成功的解决了这个问题。问题如下图解决步骤:服务器开机..._there is no sata device

【数据结构】史上最好理解的红黑树讲解,让你彻底搞懂红黑树-程序员宅基地

文章浏览阅读10w+次,点赞719次,收藏3.6k次。狂肝半个月的学习笔记,最通俗易懂的红黑树讲解。带你快速掌握红黑树~_红黑树

SDUTACM 数据结构实验之图论八:欧拉回路_欧拉回路的结点个数-程序员宅基地

文章浏览阅读362次。题目描述在哥尼斯堡的一个公园里,有七座桥将普雷格尔河中两个岛及岛与河岸连接起来。能否走过这样的七座桥,并且每桥只走一次?瑞士数学家欧拉最终解决了这个问题并由此创立了拓扑学。欧拉通过对七桥问题的研究,不仅圆满地回答了哥尼斯堡七桥问题,并证明了更为广泛的有关一笔画的三条结论,人们通常称之为欧拉定理。对于一个连通图,通常把从某结点出发一笔画成所经过的路线叫做欧拉路。人们又通常把一_欧拉回路的结点个数

推荐文章

热门文章

相关标签