返回线程中的信息(回调)

从结束的线程中返回信息,注意到run()方法和start()方法不返回任意值。可以用‘回调’实现!

案例如下(详见Java网络编程3th):

package callback;
/*
 * 如何获得线程输出?
 * 1.直接使用存取方法如get()获得线程输出,这种方法会由于主线程和其它线程步调不一致,
 *   主函数中使用线程中返回的对象时,可能此时对象还未在线程中完成初始化.
 *   可以使用轮询(while(xxx!=null))测试.
 * 2.回调.当线程的run方法接近结束时,基于结果调用主类中的一个已知方法,
 *   可以是调用主类的静态方法也可以在线程中用主类的实例(线程类持有,可以通过构造函数传入)调用实例方法.
 *   回调机制可以处理涉及更多线程、对象和类更加复杂的情况.
 *   例如有多个对象关心线程的计算结果,那么线程可以持有一个回调对象列表.
 *   某个对象通过调用Thread或者Runnable类的一个方法把自己添加到列表中表示自己对计算结果关注.
 *   #如果有多个类的实例关心结果,可以定义一个interface(接口),让所有这些类都实现这个接口.
 *   #下面的DigestListener接口就是这样一个例子
 */
public interface DigestListener {
	//此接口声明了digestCalculated方法,此方法将作为线程中的回调方法
	public void digestCalculated(byte[] digest);
}

package callback;

import java.io.*;
import java.security.DigestInputStream;
import java.security.MessageDigest;
import java.util.List;
import java.util.ListIterator;
import java.util.Vector;

/*
 * 计算文件摘要的Runnable类
 */
public class ListcallBackDigest implements Runnable {

	private File input;//文件源
	List listennerList=new Vector();//存放回调对象的列表
	
	public ListcallBackDigest(File input){
		this.input=input;
	}
	//-------向回调对象的列表中添加对象(实现了DigestListener接口的)---------
	public synchronized void addDigestListenner(DigestListener l){
		listennerList.add(l);
	}
	
	public synchronized void removeDigestListenner(DigestListener l){
		listennerList.remove(l);
	}
	//----------------向列表中存的所有回调对象发送回调请求-----------------
	private synchronized void sendDigest(byte[] digest){
		ListIterator itrator=listennerList.listIterator();
		while(itrator.hasNext()){
			DigestListener dl=(DigestListener) itrator.next();
			//为每一个回调对象调用回调函数,从线程向目标对象返回信息,本例中的目标对象主要完成文件摘要的计算
			dl.digestCalculated(digest);
		}
	}
	
	public void run() {
		try {
			FileInputStream in=new FileInputStream(input);
			MessageDigest sha=MessageDigest.getInstance("SHA");
			DigestInputStream din=new DigestInputStream(in, sha);
			int b;
			while((b=din.read())!=-1);//不断读取
			din.close();
			byte[] digest=sha.digest();
			this.sendDigest(digest);//线程的最后调用回调方法,传回信息
			
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
}
package callback;
import java.io.*;
public class UserInterface implements DigestListener{
	public static long beginTime ;
	private File input;
	private byte[] digest;//保存线程传回来的数据
	public UserInterface(File input){
		this.input=input;
	}
	//--------实际启动线程的方法------------
	public void calculatDigest(int i){
		ListcallBackDigest lcb=new ListcallBackDigest(input);
		lcb.addDigestListenner(this);//添加当前对象
		Thread t=new Thread(lcb);
		t.setName("线程"+(i+1));
		t.start();
	}
	@Override
	//------------回调的方法-------------
	public void digestCalculated(byte[] digest) {
		// TODO Auto-generated method stub
		this.digest=digest;
		System.out.print(this);//下面要重写该类的ToString方法
		long endTime = System.currentTimeMillis();//记录当前系统时间
		System.out.println(Thread.currentThread().getName()+":"+"耗时 "+(endTime-beginTime)/1000+"秒");
	}
	
	public String toString(){
		String res=input.getName()+":";
		if(digest!=null){
			for(int i=0;i<digest.length;i++){
				res+=digest[i]+" ";
			}
		}else
			res+="digest not available!";
		return res;
	}
	//-------------主函数---------------
	public static void main(String[] args) {
		beginTime = System.currentTimeMillis();//记录当前系统时间
		for(int i=0;i<args.length;i++){
			File f=new File(args[i]);
			UserInterface u=new UserInterface(f);
			u.calculatDigest(i);
		}
		System.out.println("main()结束!");
	}

}

可以参考上一篇文章http://blog.csdn.net/hellozpc/article/details/42027539

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。