`
chen291382932
  • 浏览: 6624 次
  • 性别: Icon_minigender_1
  • 来自: 郑州
社区版块
存档分类
最新评论

从线程返回数据的两种方法

 
阅读更多

从线程中返回数据和向线程传递数据类似。也可以通过类成员以及回调函数来返回数据。但类成员在返回数据和传递数据时有一些区别,下面让我们来看看它们区别在哪。

一、通过类变量和方法返回数据

使用这种方法返回数据需要在调用start方法后才能通过类变量或方法得到数据。让我们先来看看例程2-13会得到什么结果。

  1. package mythread;  
  2.  
  3. public class MyThread extends Thread  
  4. {  
  5.     private String value1;  
  6.     private String value2;  
  7.  
  8.     public void run()  
  9.     {  
  10.         value1 = "通过成员变量返回数据";  
  11.         value2 = "通过成员方法返回数据";  
  12.     }  
  13.     public static void main(String[] args) throws Exception  
  14.     {  
  15.         MyThread thread = new MyThread();  
  16.         thread.start();  
  17.         System.out.println("value1:" + thread.value1);  
  18.         System.out.println("value2:" + thread.value2);  
  19.     }  
  20. }  

运行上面的代码有可能输出如下的结果:

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时,就可以输出这两个值了。我们可以使用如下的代码来达到这个目的:

  1. while (thread.value1 == null || thread.value2 == null); 

使用上面的语句可以很稳定地避免这种情况发生,但这种方法太耗费系统资源。大家可以设想,如果run方法中的代码很复杂,value1和value2需要很长时间才能被赋值,这样while循环就必须一直执行下去,直到value1和value2都不为空为止。因此,我们可以对上面的语句做如下的改进:

  1. while (thread.value1 == null || thread.value2 == null)  
  2.     sleep(100); 

在while循环中第判断一次value1和value2的值后休眠100毫秒,然后再判断这两个值。这样所占用的系统资源会小一些。

上面的方法虽然可以很好地解决,但Java的线程模型为我们提供了更好的解决方案,这就是join方法。在前面已经讨论过,join的功能就是使用线程从异步执行变成同步执行。当线程变成同步执行后,就和从普通的方法中得到返回数据没有什么区别了。因此,可以使用如下的代码更有效地解决这个问题:

thread.start();
thread.join();

在thread.join()执行完后,线程thread的run方法已经退出了,也就是说线程thread已经结束了。因此,在thread.join()后面可以放心大胆地使用MyThread类的任何资源来得到返回数据。

二、通过回调函数返回数据

其实这种方法已经在《向线程传递数据的三种方法》中介绍了。在《向线程传递数据的三种方法》一文的例子中通过Work类的process方法向线程中传递了计算结果,但同时,也通过process方法从线程中得到了三个随机数。因此,这种方法既可以向线程中传递数据,也可以从线程中获得数据。

分享到:
评论

相关推荐

    Java多线程初学者指南(7):向线程传递数据的三种方法.docx )

    上面讨论的两种向线程中传递数据的方法都是 main 方法中主动将数据传入线程类的。这对于线程来说,是被动接收这些数据的。然而,在有些应用中需要在线程运行的过程中动态地获取数据。例如,以下代码演示了如何使用回...

    java多线程编程之从线程返回数据的两种方法

    从线程中返回数据和向线程传递数据类似。也可以通过类成员以及回调函数来返回数据。但类成员在返回数据和传递数据时有一些区别,下面让我们来看看它们区别在哪

    COM串口协议通讯客户端服务器发送数据

    C#串口监听的实现由于串口不知道数据何时到达,因此有两种方法可以实现C#串口监听之串口数据的读取。1.用线程实时读串口2.用事件触发方式实现。但由于线程实时读串口的效率不是十分高效,因此比较好的方法是事件触发...

    Linux系统编程之线程同步

    【作业】:编写程序,实现上述两种死锁现象。 读写锁 与互斥量类似,但读写锁允许更高的并行性。其特性为:写独占,读共享。 读写锁状态: 一把读写锁具备三种状态: 1. 读模式下加锁状态 (读锁) 2. ...

    Delphi多线程编程之三 同步读写全局数据

    三、还有一种用信号量对象来管理线程同步的,它是在互斥的基础上建立的,但信号量增加了资源计数的功能,预定数目的线程允许同时进入要同步的代码。有点复杂,想不到在哪可以用,现在就不研究论了。 unit Tst_...

    linux系统编程之线程.zip

    在一个线程中调用pthread_create()创建新的线程后,当前线程从pthread_create()返回继续往下执行,而新的线程所执行的代码由我们传给pthread_create的函数指针start_routine决定。start_routine函数接收一个参数,是...

    DSPBIOS多线程入门级要点

    每个SWI都有一个32bit的邮箱,可以作为能否分配一个SWI线程的信号量,用SWI_getmbox可以返回邮箱值,返回值为SWI从就绪队列中退出开始执行前的邮箱值,SWI执行后mailbox值恢复初始值。 SWI函数有SWI_post,SWI_or,...

    C#实现向多线程传参的三种方式实例分析

    从《C#高级编程》了解到给线程传递参数有两种方式,一种方式是使用带ParameterizedThreadStart委托参数的Thread构造函数,另一种方式是创建一个自定义类,把线程的方法定义为实例的方法,这样就可以初始化实例的数据...

    Java多线程与线程安全实践-基于Http协议的断点续传

    在Http请求中,常见的请求方法有GET和POST两种,其中GET方法用于获取资源,POST方法用于提交数据。在Http响应中,常见的状态码有200、404、500等,表示请求成功、请求的资源不存在、服务器内部错误等不同情况。 ...

    QTcpThreadPoolServiceTest

    有两种均衡方法。 一种是生产者粒度的均衡。同一个生产者的各批数据FIFO顺序不被打破,这需要判断,当处理线程队列中还有该生产者的数据时,不改变当前处理线程。 第二种是数据粒度的并行,某个生产者传来的数据被...

    java笔试题大集合及答案(另附各大公司笔试题)

    60、java中有几种方法可以实现一...答:多线程有两种实现方法,分别是继承Thread类与实现Runnable接口 同步的实现方面有两种,分别是synchronized,wait与notify 67、线程的基本概念、线程的基本状态以及状态之间的关系

    Java Socket编程实现的简单多线程WEB服务器

    当有客户端连接到服务器时,accept() 方法将返回一个 Socket 对象,我们可以使用这个对象来与客户端进行通信。 多线程编程 在我们的示例代码中,我们使用多线程编程来处理来自客户端的连接请求。每当有客户端连接...

    pthread_doc

    * __inheritsched,有两种值可供选择:pthread_EXPLICIT_SCHED 和 pthread_INHERIT_SCHED,前者表示新线程使用显式指定调度策略和调度参数(即 attr 中的值),而后者表示继承调用者线程的值。 * __scope,表示线程...

    基本数据类型包装类.pdf

    基本数据类型包装类是 Java 语言中的一种机制,用于将基本数据类型封装成对象。这些对象可以被存储在集合中、作为方法的参数、返回值等。在 Java 中,基本数据类型包装类包括 Byte、Short、Integer、Long、Character...

    江神JAVA开发面经超级总结

    进程的通信方式有两种:进程通信和线程通信。进程通信方式有管道、消息队列、共享内存等。线程通信方式有同步和异步。 十三、线程同步方式 线程同步方式有三种:互斥锁、信号量和条件变量。互斥锁用于保护共享资源...

    IO复用服务器linux C语言开发的包含客户端

    1,服务与客户端以两种格式进行数据发送,一个是以char数组,一个是以struct(就在头文件以内) 2,使用了IO复用(select监测)进行服务器编程 3,服务器总共使用一个进程,两个线程。(代码注解实际项目之中,以四...

    超级有影响力霸气的Java面试题大全文档

    此数组元素数大于实际存储的数据以便增加和插入元素,它们都允许直接按序号索引元素,但是插入元素要涉及数组元素移动等内存操作,所以索引数据快而插入数据慢,Vector由于使用了synchronized方法(线程安全),...

    C++串口编程(VC)

    对于dwAttrsAndFlags参数及FILE_FLAG_OVERLAPPED标志的由来,可解释如下:Windows文件操作分为同步I/O和重叠I/O(Overlapped I/ O)两种方式,在同步I/O方式中,API会阻塞直到操作完成以后才能返回(在多线程方式中,...

    java 面试题 总结

    此数组元素数大于实际存储的数据以便增加和插入元素,它们都允许直接按序号索引元素,但是插入元素要涉及数组元素移动等内存操作,所以索引数据快而插入数据慢,Vector由于使用了synchronized方法(线程安全),...

    数据库分表处理设计思想和实现

    就是说,如果前一个SQL没有执行完毕的话,后面的SQL是不会执行的,因为为了保证数据的完整性,必须对数据表文件进行锁定,包括共享锁和独享锁两种锁定。共享锁是在锁定的期间,其它线程也可以访问这个数据文件,但是...

Global site tag (gtag.js) - Google Analytics