关于主线程获取子线程数据

在主线程中获取子线程的数据,解决项目中的问题。

在进行多线程编程中,比较重要也是比较困难的一个操作就是如何获取线程中的信息。

轮询

比较常见的一种解决方案是,让线程类获取方法在结果字段设置之前返回一个标志值。然后主线程定时询问获取方法,看是否返回了标志之外的值。该方法不断测试str的值是否为”Hello”,如果不为”Hello”才打印输出它。例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package threadtest1;

public class Main{

/**
* @param args the command line arguments
*/
public static void main(String[] args) {
ReturnThreadInfo returnThreadInfo = new ReturnThreadInfo();
returnThreadInfo.start(); //创建并启动ReturnThreadInfo线程

while(true){
String str = returnThreadInfo.getThreadInfo();
if(!str.equals("Hello")){
System.out.println(returnThreadInfo.getThreadInfo());
break;
}
}
}
}

这种方案虽然能起到作用,但是它做了大量不需要做的工作。事实上,还有一种更简单有效的方法来解决这个问题。

回调

轮询方法最大的特点是主类Main不断询问线程类是否结束,这实际上大量浪费了运行时间,特别是当线程特别多的时候。因此如果反过来在线程结束时,由线程自己告诉主类Main线程已经结束,然后Main再获取并输出str的值,这样就避免了轮询方法所带来的不必要的系统开销问题。
在具体的实现过程中,线程可以在结束时通过调用主类中的一个方法来实现告知功能,这种方法叫做回调。这样主类Main就可以在等待线程结束时休息,也就不会占用运行线程的时间。下面是修改后的Main类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class Main{

/**
* @param args the command line arguments
*/
public static void main(String[] args) {
// TODO code application logic here
ReturnThreadInfo returnThreadInfo = new ReturnThreadInfo();
returnThreadInfo.start();
}

public static void receiveStr(String str){
System.out.println(str);
}
}

相比于前面,我们在Main类中添加了一个静态方法receiveStr(String str),该方法是供线程结束之前调用,通过参数str将要返回的线程信息返回给Main类并输出显示出来。下面是修改后的ReturnThreadInfo类,该类在线程结束前回调了Main.receiveStr方法,通知线程已结束。

1
2
3
4
5
6
7
8
9
10
11
package threadtest1;
public class ReturnThreadInfo extends Thread {
private String str;
public ReturnThreadInfo() {
this.str = "Hello";
}
public void run(){
this.str = "Hello World!";
Main.receiveStr(str); //回调receiveStr方法
}
}

如果有很多个对象关心线程的返回的信息,线程可以保存一个回调对象列表。某个对象可以通过已经定义的一个对象将自己添加到列表中,表示自己对这些信息的关注。如果有多个类的实例关心这些信息,也可以定义一个interface,在interface中声名回调方法,然后这些类都实现这个接口。其实这是典型的java处理事件的方法,这么做可以使得回调更灵活,可以处理涉及更多线程、对象和类的情况。

:转载文章请注明出处,谢谢~