原文地址:http://smalltalllong.iteye.com/blog/1156407
在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.Random 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方法中引发了一个事件
相关推荐
然而,Python的`threading`模块本身并不直接支持获取线程函数的返回值,这需要我们通过一些额外的方式来实现。以下将详细解释如何在Python中使用`threading`获取线程函数的返回值。 首先,我们需要理解`threading`...
5. **线程返回值**: - 线程函数可以通过`ExitThread()`函数设置线程的退出代码,这个值可以通过`GetExitCodeThread()`函数获取。 - 在VC++中,主线程可以通过`Joinable`线程类的`join()`成员函数等待子线程结束并...
通过阅读源码,你可以了解到实际应用中的具体实现方式,包括线程创建、数据交换以及返回的逻辑。 总结,易语言线程返回数据的方法涉及到线程的创建、数据共享机制和同步策略等多个方面。开发者需要根据实际需求选择...
在C++多线程编程中,获取线程返回值是一个很重要的 topic。在C++11标准中,std::thread对象会忽略顶层函数的返回值,这就使得获取线程返回值变得困难。下面我们将详细介绍两种获取返回值的方法:传统方法和C++11方法...
NULL 博文链接:https://icgemu.iteye.com/blog/467848
C++11获取线程返回值的实现代码 在C++11中,获取线程返回值是一个常见的需求。传统的方法是使用指针共享数据,但是这种方法需要使用条件变量和互斥量,编程过程复杂且容易出错。幸运的是,C++11提供了std::future和...
标题中的“有返回值的线程”指的是在编程中如何在线程执行完后获取到一个结果。线程通常用于执行异步任务,而当我们需要这些任务执行的结果时,就需要用到带返回值的线程机制。Java语言中,可以通过实现`Callable`...
大家都知道实现多线程的2种方式,今天来讲讲Future实现具有返回值的线程。应用场景:前端调用时无需等待线程结束返回,线程结束后需进行其它操作如更新状态、通知kafuka等。
最近有个需求,用多线程比较合适,但是我需要每个线程的返回值,这就需要我在threading.Thread的基础上进行封装 import threading class MyThread(threading.Thread): def __init__(self,func,args=()): super...
这个`parse_detail_page`函数可以处理多个URL,每个URL都在一个独立的线程中处理,最后返回一个包含所有线程返回值的列表。 需要注意的是,使用`join()`方法是必要的,因为它确保主线程等待所有子线程结束,防止在...
大家都知道Runnable和Callable接口都可以作为其他线程执行的任务,但是Runnable接口的run方法没有返回值,而Callable接口的call方法有返回值,那么Callable接口是如何做到的呢?在此我给出一个Demo,看看通过...
"C#多线程函数如何传参数和返回值" 在C#中,多线程函数的参数传递和返回值处理是非常重要的。多线程函数可以使用委托(delegates)来实现参数的传递和返回值的处理。 委托是具有同样参数和返回值的函数的集合。...
在多线程环境下,线程间的通信通常通过共享内存、信号量、消息队列等方式实现。在易语言中,由于其特性,我们可以使用“设置线程变量”和“获取线程变量”这两个命令来传递线程间的数据。下面是一个简单的例子,演示...
为了解决这个问题,Java提供了`Callable`接口和`FutureTask`类,它们是实现多线程返回值的关键工具。 `Callable`接口类似于`Runnable`,但比它功能更强大。`Callable`接口中的`call()`方法可以返回一个结果,并且...
通过几个实验练习,学习线程之间连接的具体实现。下面列举了两个例子,一个是子线程返回简单数据类型;另一个是子线程返回复杂数据类型。 实现代码 子线程返回复杂数据类型 #include #include #include #include ...
Java使用Callable和Future创建线程操作示例主要介绍了Java使用Callable和Future创建线程操作,结合实例形式分析了java使用Callable接口和Future类创建线程的相关操作技巧与注意事项。 首先,Java 5开始,Java提供了...