返回线程中的信息(回调)
从结束的线程中返回信息,注意到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
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。