• 博客
  • 微博
  • 相册
  • 收藏
  • 留言
  • 关于我

线程返回值的方式介绍

博客分类:

  • 多线程
Java代码  
  1. 在Java5之前,线程是没有返回值的,常常为了“有”返回值,破费周折,而且代码很不好写。或者干脆绕过这道坎,走别的路了。
  2. 现在Java终于有可返回值的任务(也可以叫做线程)了。
  3. 可返回值的任务必须实现Callable接口,类似的,无返回值的任务必须Runnable接口。
  4. 执行Callable任务后,可以获取一个Future的对象,在该对象上调用get就可以获取到Callable任务返回的Object了。
  5. 下面是个很简单的例子:
  6. Java代码
  7. import java.util.concurrent.*;
  8. /**
  9. * Java线程:有返回值的线程
  10. *
  11. * @author Administrator
  12. */
  13. public class Test {
  14. public static void main(String[] args) throws ExecutionException, InterruptedException {
  15. //创建一个线程池
  16. ExecutorService pool = Executors.newFixedThreadPool(2);
  17. //创建两个有返回值的任务
  18. Callable c1 = new MyCallable("A");
  19. Callable c2 = new MyCallable("B");
  20. //执行任务并获取Future对象
  21. Future f1 = pool.submit(c1);
  22. Future f2 = pool.submit(c2);
  23. //从Future对象上获取任务的返回值,并输出到控制台
  24. System.out.println(">>>"+f1.get().toString());
  25. System.out.println(">>>"+f2.get().toString());
  26. //关闭线程池
  27. pool.shutdown();
  28. }
  29. }
  30. class MyCallable implements Callable{
  31. private String oid;
  32. MyCallable(String oid) {
  33. this.oid = oid;
  34. }
  35. @Override
  36. public Object call() throws Exception {
  37. return oid+"任务返回的内容";
  38. }
  39. }
  40. 输出结果:
  41. >>>A任务返回的内容
  42. >>>B任务返回的内容
  43. Process finished with exit code 0
  44. 非常的简单,要深入了解还需要看Callable和Future接口的API啊。
  45. 第二种方法:
  46. 从线程中返回数据和向线程传递数据类似。也可以通过类成员以及回调函数来返回数据。但类成员在返回数据和传递数据时有一些区别,下面让我们来看看它们区别在哪。
  47.   一、通过类变量和方法返回数据
  48.   使用这种方法返回数据需要在调用start方法后才能通过类变量或方法得到数据。让我们先来看看会得到什么结果。
  49. Java代码
  50. package mythread;
  51. public class MyThread extends Thread
  52. {
  53.     private String value1;
  54.     private String value2;
  55.     public void run()
  56.     {
  57.         value1 = "通过成员变量返回数据";
  58.         value2 = "通过成员方法返回数据";
  59.     }
  60.     public static void main(String[] args) throws Exception
  61.     {
  62.         MyThread thread = new MyThread();
  63.         thread.start();
  64.         System.out.println("value1:" + thread.value1);
  65.         System.out.println("value2:" + thread.value2);
  66.     }
  67. }
  68. 运行上面的代码有可能输出如下的结果:
  69.   value1:null
  70.   value2:null
  71.   从上 面的运行结果看很不正常。在run方法中已经对value1和value2赋了值,而返回的却是null。发生这种情况的原因是调用start方法后就立 刻输出了value1和value2的值,而这里run方法还没有执行到为value1和value2赋值的语句。要避免这种情况的发生,就需要等run 方法执行完后才执行输出value1和value2的代码。因此,我们可以想到使用sleep方法将主线程进行延迟,如可以在 thread.start()后加一行如下的语句:sleep(1000);
  72.   这样做可以使主线程延迟1秒后再往下执行,但这样做有一个问题,就是我们怎么知道要延迟多长时间。在这 个例子的run方法中只有两条赋值语句,而且只创建了一个线程,因此,延迟1秒已经足够,但如果run方法中的语句很复杂,这个时间就很难预测,因此,这 种方法并不稳定。
  73.   我们的目的就是得到value1和value2的值,因此,只要判断value1和value2是否为null。如果它们都不为null时,就可以输出这两个值了。我们可以使用如下的代码来达到这个目的:
  74.   while (thread.value1 == null || thread.value2 == null);
  75.    使用上面的语句可以很稳定地避免这种情况发生,但这种方法太耗费系统资源。大家可以设想,如果run方法中的代码很复杂,value1和value2需 要很长时间才能被赋值,这样while循环就必须一直执行下去,直到value1和value2都不为空为止。因此,我们可以对上面的语句做如下的改进:
  76.   while (thread.value1 == null || thread.value2 == null)
  77.    sleep(100);
  78.   在while循环中第判断一次value1和value2的值后休眠100毫秒,然后再判断这两个值。这样所占用的系统资源会小一些。
  79.    上面的方法虽然可以很好地解决,但Java的线程模型为我们提供了更好的解决方案,这就是join方法。在前面已经讨论过,join的功能就是使用线程 从异步执行变成同步执行。当线程变成同步执行后,就和从普通的方法中得到返回数据没有什么区别了。因此,可以使用如下的代码更有效地解决这个问题:
  80. Java代码
  81. ...
  82. thread.start();
  83. thread.join();
  84. ...
  85. 在thread.join()执行完后,线程thread的run方法已经退出了,也就是说线程thread已经结束了。因此,在thread.join()后面可以放心大胆地使用MyThread类的任何资源来得到返回数据。 
  86. 第三种:
  87. 通过回调函数返回数据
  88.   下面例子中通过Work类的process方法向线程中传递了计算结果,但同时,也通过process方法从线程中得到了三个随机数。因此,这种方法既可以向线程中传递数据,也可以从线程中获得数据。
  89. Java代码
  90. package mythread;
  91. class Data
  92. {
  93. public int value = 0;
  94. }
  95. class Work
  96. {
  97. public void process(Data data, Integer numbers)
  98. {
  99. for (int n : numbers)
  100. {
  101. data.value += n;
  102. }
  103. }
  104. }
  105. public class MyThread3 extends Thread
  106. {
  107. private Work work;
  108. public MyThread3(Work work)
  109. {
  110. this.work = work;
  111. }
  112. public void run()
  113. {
  114. java.util.Random random = new java.util.Random();
  115. Data data = new Data();
  116. int n1 = random.nextInt(1000);
  117. int n2 = random.nextInt(2000);
  118. int n3 = random.nextInt(3000);
  119. work.process(data, n1, n2, n3);   // 使用回调函数
  120. System.out.println(String.valueOf(n1) + "+" + String.valueOf(n2) + "+"
  121. + String.valueOf(n3) + "=" + data.value);
  122. }
  123. public static void main(String[] args)
  124. {
  125. Thread thread = new MyThread3(new Work());
  126. thread.start();
  127. }
  128. }
  129. 在上面代码 中的 process方法被称为回调函数。从本质上说,回调函数就是事件函数。在 Windows API中常使用回调函数和调用 API的程序之间进行数据交互。因此,调用回调函数的过程就是最原始的引发事件的过程。在这个例子中调用了 process方法来获得数据也就相当于在 run方法中引发了一个事件

转载于:https://www.cnblogs.com/leo3689/p/4408954.html

线程返回值的方式介绍相关推荐

  1. python 子线程返回值_python-从线程返回值

    python-从线程返回值 我如何获得一个线程以将元组或我选择的任何值返回给Python中的父级? 12个解决方案 59 votes 我建议您在启动线程之前实例化Queue.Queue,并将其作为线程 ...

  2. python多线程处理数据并获得子线程返回值

    python多线程处理数据并获得子线程返回值 前言 python3中的多线程 用方法包装函数 用类包装函数 获取子线程返回值 从类中返回值 其他方法 前言 python中采用多线程方式处理大数据量的数 ...

  3. Python 获取线程返回值获取

    Python 获取线程返回值获取 思路 重写run方法,使用线程的get_result()方法获取返回结果 '''示例: 多线程访问百度,统计平均响应时间和错误率''' class MyThread( ...

  4. MyBatis查询结果resultType返回值类型详细介绍

    一.返回一般数据类型 比如要根据 id 属性获得数据库中的某个字段值. mapper 接口: // 根据 id 获得数据库中的 username 字段的值String getEmpNameById(I ...

  5. C语言 线程的回收与子线程返回值的接收

    穿的参数为二级指针 需要用全局变量来返回子线程的返回值 // ..使用内存映射可以拷贝文件 /* 对原始文件进行内存映射 创建一个新文件 把新文件的数据拷贝映射到内存中 通过内存拷贝将第一个文件的内存 ...

  6. Future获取线程返回值能使线程顺序执行?

    2019独角兽企业重金招聘Python工程师标准>>> 线程非安全的方法getNext() import net.jcip.annotations.NotThreadSafe;@No ...

  7. 【Kotlin】Lambda 表达式 ( 简介 | 表达式语法 | 表达式类型 | 表达式返回值 | 调用方式 | 完整示例 )

    文章目录 I . Lambda 表达式 简介 II . Lambda 表达式语法 III . Lambda 表达式类型 IV . Lambda 表达式返回值 V . Lambda 表达式调用 VI . ...

  8. 【Python教程】 re 模块中findall() 函数返回值展现方式的用法详解

    findall 函数: 在字符串中找到正则表达式所匹配的所有子串,并返回一个列表,如果没有找到匹配的,则返回空列表. 注意: match 和 search 是匹配一次 findall 匹配所有,mat ...

  9. Python re 模块findall() 函数返回值展现方式详解

    findall 函数: 在字符串中找到正则表达式所匹配的所有子串,并返回一个列表,如果没有找到匹配的,则返回空列表. 注意: match 和 search 是匹配一次 findall 匹配所有,mat ...

最新文章

  1. golang 编译后文件过大问题处理
  2. 修改pom文件_SpringCloud微服务全家桶-第8篇,服务的配置文件更改
  3. QT pro文件解析
  4. How-to: Use the ShareLib in Apache Oozie
  5. 现在的便签本都这么社会了!?重复写万次还能云端保存
  6. 各浏览器的Hack写法【转】
  7. LVS-DR工作原理图文详解(转载)
  8. 基于OMAPL138/C6748 + SPARTAN-6 77GHz汽车防撞雷达信号处理平台设计
  9. 边读边捋【july的】海量数据处理面试题
  10. 将字体变成红色加粗字体
  11. 《麦肯锡精英的谈判策略》 -豆瓣评分8.2
  12. web前端编程实战实例:制作静态京东首页
  13. 诺基亚5800 XM实测
  14. 011 符号计算-积分、微分、极限、积分变换、方程求解
  15. 打造一个window桌面应用:在线聊天对话机器人
  16. 医疗汇报医学演示PPT模板
  17. 自己开发CMS系统还是使用成熟的CMS系统?
  18. 「津津乐道播客」#254. 津津有味:对不起,我不想再跟你吃饭了
  19. unittest自动化测试-测试夹具TestFixtrue与忽略测试用例方法
  20. 计算机软故障无法开机,电脑常见的开机故障及解决方法的详解

热门文章

  1. 线性回归模型原理及推导
  2. “人工智能=统计+计算”:专家表示人工智能无需“智能”
  3. SAP MM MIGO Return Delivery 组合实现部分数量的Reversal
  4. 学 AI 和机器学习的人必须关注的 6 个领域
  5. 零售行业SAP项目 --- SAP顾问向大数据转型的契机
  6. Xmanager7如何通过SSH连接远程服务器
  7. 乖乖给行人让路?学界推出无人机控制技术NMPC,可在低空中实现自主导航和避障...
  8. 关于征集2020重大科学问题和工程技术难题的通知
  9. 语音助手再次敲响隐私保护警钟
  10. CNNIC互联网报告:中国网民超8亿 前沿科技进展显著