首页
.NET
SEO
数据库
JAVA
电商
旅游
科学
UFO
天文
地理
生命
时尚
时装
美容
旅游攻略
跨境电商
亚马逊
Shopee
家居
别墅
时尚
体育
足球
娱乐
女人
保健
手机版
首页
跨境电商
亚马逊
Shopee
阿里巴巴
沃尔玛
Lazada
eBay
速卖通
wish
Shopify
Joom
Cdiscount
独立站
Facebook
Google
TikTok
TEMU
敦煌网
Jumia
Ozon
Fordeal
Fnac
Wayfair
乐天
VOVA
Coupang
Allegro
软件开发
ASP.net
Java
ASP
网页设计
网络
操作系统
数据库
ajax
多媒体
营销推广
SEO
ASO
微信推广
移动互联网
品牌营销
游戏推广
渠道推广
产品运营
产品运营
私域运营
社群运营
用户运营
活动运营
短视频运营
抖音
视频号
快手
TikTok
你的位置:
首页
>
软件开发
>
Java
> 线程返回值的方式介绍
线程返回值的方式介绍
发布时间:2015-04-09 12:00:19
博客微博相册收藏留言关于我 线程返回值的方式介绍博客分类: 多线程 Java代码 在Java5之前,线程是没有返回值的,常常为了“有”返回值,破费周折,而且代码很不好写。或者干脆绕过这道坎,走别的路了。 ...
博客
微博
相册
收藏
留言
关于我
线程
返回值的方式介绍
博客分类:
多线程
Java
代码
在Java5之前,线程是没有返回值的,常常为了“有”返回值,破费周折,而且代码很不好写。或者干脆绕过这道坎,走别的路了。
现在Java终于有可返回值的任务(也可以叫做线程)了。
可返回值的任务必须实现Callable
接口
,类似的,无返回值的任务必须Runnable接口。
执行Callable任务后,可以获取一个Future的对象,在该对象上调用get就可以获取到Callable任务返回的Object了。
下面是个很简单的例子:
Java代码
import java.util.concurrent.*;
/**
* Java线程:有返回值的线程
*
* @author Administrator
*/
public class Test {
public static void main(String[] args) throws ExecutionException, InterruptedException {
//创建一个线程池
ExecutorService pool = Executors.newFixedThreadPool(2);
//创建两个有返回值的任务
Callable c1 = new MyCallable("A");
Callable c2 = new MyCallable("B");
//执行任务并获取Future对象
Future f1 = pool.submit(c1);
Future f2 = pool.submit(c2);
//从Future对象上获取任务的返回值,并输出到控制台
System.out.println(">>>"+f1.get().toString());
System.out.println(">>>"+f2.get().toString());
//关闭线程池
pool.shutdown();
}
}
class MyCallable implements Callable{
private String oid;
MyCallable(String oid) {
this.oid = oid;
}
@Override
public Object call() throws Exception {
return oid+"任务返回的内容";
}
}
输出结果:
>>>A任务返回的内容
>>>B任务返回的内容
Process finished with exit code 0
非常的简单,要深入了解还需要看Callable和Future接口的API啊。
第二种方法:
从线程中返回数据和向线程传递数据类似。也可以通过类成员以及回调
函数
来返回数据。但类成员在返回数据和传递数据时有一些区别,下面让我们来看看它们区别在哪。
一、通过类变量和方法返回数据
使用这种方法返回数据需要在调用start方法后才能通过类变量或方法得到数据。让我们先来看看会得到什么结果。
Java代码
package mythread;
public class MyThread extends Thread
{
private String value1;
private String value2;
public void run()
{
value1 = "通过成员变量返回数据";
value2 = "通过成员方法返回数据";
}
public static void main(String[] args) throws Exception
{
MyThread thread = new MyThread();
thread.start();
System.out.println("value1:" + thread.value1);
System.out.println("value2:" + thread.value2);
}
}
运行上面的代码有可能输出如下的结果:
value1:null
value2:null
从上 面的运行结果看很不正常。在run方法中已经对value1和value2赋了值,而返回的却是null。发生这种情况的原因是调用start方法后就立 刻输出了value1和value2的值,而这里run方法还没有执行到为value1和value2赋值的语句。要避免这种情况的发生,就需要等run 方法执行完后才执行输出value1和value2的代码。因此,我们可以想到使用sleep方法将主线程进行延迟,如可以在 thread.start()后加一行如下的语句:sleep(1000);
这样做可以使主线程延迟1秒后再往下执行,但这样做有一个问题,就是我们怎么知道要延迟多长时间。在这 个例子的run方法中只有两条赋值语句,而且只创建了一个线程,因此,延迟1秒已经足够,但如果run方法中的语句很复杂,这个时间就很难预测,因此,这 种方法并不稳定。
我们的目的就是得到value1和value2的值,因此,只要判断value1和value2是否为null。如果它们都不为null时,就可以输出这两个值了。我们可以使用如下的代码来达到这个目的:
while (thread.value1 == null || thread.value2 == null);
使用上面的语句可以很稳定地避免这种情况发生,但这种方法太耗费系统资源。大家可以设想,如果run方法中的代码很复杂,value1和value2需 要很长时间才能被赋值,这样while循环就必须一直执行下去,直到value1和value2都不为空为止。因此,我们可以对上面的语句做如下的改进:
while (thread.value1 == null || thread.value2 == null)
sleep(100);
在while循环中第判断一次value1和value2的值后休眠100毫秒,然后再判断这两个值。这样所占用的系统资源会小一些。
上面的方法虽然可以很好地解决,但Java的线程模型为我们提供了更好的解决方案,这就是join方法。在前面已经讨论过,join的功能就是使用线程 从异步执行变成同步执行。当线程变成同步执行后,就和从普通的方法中得到返回数据没有什么区别了。因此,可以使用如下的代码更有效地解决这个问题:
Java代码
...
thread.start();
thread.join();
...
在thread.join()执行完后,线程thread的run方法已经退出了,也就是说线程thread已经结束了。因此,在thread.join()后面可以放心大胆地使用MyThread类的任何资源来得到返回数据。
第三种:
通过回调函数返回数据
下面例子中通过Work类的process方法向线程中传递了计算结果,但同时,也通过process方法从线程中得到了三个
随机
数。因此,这种方法既可以向线程中传递数据,也可以从线程中获得数据。
Java代码
package mythread;
class Data
{
public int value = 0;
}
class Work
{
public void process(Data data, Integer numbers)
{
for (int n : numbers)
{
data.value += n;
}
}
}
public class MyThread3 extends Thread
{
private Work work;
public MyThread3(Work work)
{
this.work = work;
}
public void run()
{
java.util.Ran
dom
random = new java.util.Random();
Data data = new Data();
int n1 = random.nextInt(1000);
int n2 = random.nextInt(2000);
int n3 = random.nextInt(3000);
work.process(data, n1, n2, n3); // 使用回调函数
System.out.println(String.valueOf(n1) + "+" + String.valueOf(n2) + "+"
+ String.valueOf(n3) + "=" + data.value);
}
public static void main(String[] args)
{
Thread thread = new MyThread3(new Work());
thread.start();
}
}
在上面代码 中的 process方法被称为回调函数。从本质上说,回调函数就是事件函数。在
Windows
API中常使用回调函数和调用 API的程序之间进行数据交互。因此,调用回调函数的过程就是最原始的引发事件的过程。在这个例子中调用了 process方法来获得数据也就相当于在 run方法中引发了一个事件
海外公司注册、海外银行开户、跨境平台代入驻、VAT、EPR等知识和在线办理:
https://www.xlkjsw.com
原标题:线程返回值的方式介绍
关键词:线程
线程
*特别声明:以上内容来自于网络收集,著作权属原作者所有,如有侵权,请联系我们: admin#shaoqun.com (#换成@)。
亚马逊将推出“免费1日达”?沃尔玛还坐得住吗
:https://www.ikjzd.com/articles/59900
亚马逊搜索功能停运约2小时,美国数千人投诉!
:https://www.ikjzd.com/articles/5991
预计达250亿美元!2019年母亲节购物趋势分析
:https://www.ikjzd.com/articles/59911
全球速卖通的主要运输方式及运费设置
:https://www.ikjzd.com/articles/59912
五一假日跨境电商卖家如何设置自动回复邮件?操作指南奉上
:https://www.ikjzd.com/articles/59918
英德税务问题风波未止,法国站VAT6月30日封号概率有多高?
:https://www.ikjzd.com/articles/59919
2024.04.18亚马逊选品推荐(仅供参考):女装蛋糕连衣裙
:https://www.kjdsnews.com/a/1842234.html
欧洲市场疯了,订单排到7、8月!
:https://www.kjdsnews.com/a/1842235.html
上一篇
如何在ubuntu下使用samba创建共享
下一篇
用gradle 来打包Android
相关推荐
最新文章
Java线程池详解
2017年10月1日
ScheduledThreadPoolExecutor源码分析-你知道定时线程池是如何实现延迟执行和周期执行的吗?
2020年12月3日
【实战】利用多线程优化查询百万级数据
2021年11月19日
你真的懂并发吗?谈谈对JUC线程池ThreadPoolExecutor的认识吧
2021年5月18日
Java多线程开发系列之四:玩转多线程(线程的控制2)
2015年3月2日
关于并发框架Java原生线程池原理及Guava与之的补充
2016年2月19日
hibernate学习笔记(一)
2015年4月9日
React Native – 使用 JavaScript 开发原生应用
2015年4月9日
不能被3整除的整数的和大于(或等于)2000的数字
2015年4月9日
java中的DAO设计模式
2015年4月9日
棋盘覆盖
2015年4月8日
JavaScript中的Partial Application和Currying
2015年4月8日
可能感兴趣文章
Java线程池详解
2017年10月1日
ScheduledThreadPoolExecutor源码分析-你知道定时线程池是如何实现延迟执行和周期执行的吗?
2020年12月3日
【实战】利用多线程优化查询百万级数据
2021年11月19日
你真的懂并发吗?谈谈对JUC线程池ThreadPoolExecutor的认识吧
2021年5月18日
Java多线程开发系列之四:玩转多线程(线程的控制2)
2015年3月2日
关于并发框架Java原生线程池原理及Guava与之的补充
2016年2月19日
我的浏览记录