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

从结束的线程中返回信息,注意到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

时间: 2024-12-14 04:07:55

返回线程中的信息(回调)的相关文章

Android——使用Volley+fastJson在新线程中读取网络接口获取天气信息

一,关于Volley 其实最初对于网络数据的访问,我是没想到要用框架的,使用HttpURLConnection或者HttpGet or HttpPost都可以实现.但是why? why I have to use Volley?   Before Volley: class HttpURLConnection_post extends Thread{ @Override public void run() { //设置请求的路径 String strUrl="http://api.qingyun

ThreadLocal实现session中用户信息 的线程间共享(精)

ThreadLocal并不难理解,我总结的最简单的理解就是: ThreadLocal像其它变量一样(局部.全局.静态)也是一种变量类型,只是他是线程变量,更直白的说他是一种变量作用域,即他的作用域是当前线程(比如用户的一个请求算一个线程),ThreadLocal用于在一个线程间共享. ThreadLocal的set(String,Object)方法就是设置这个变量的名称.同时给这个变量赋值.当然同时也给予了这个变量的类型. @SuppressWarnings("unchecked")

在Java 线程中返回值的用法

http://icgemu.iteye.com/blog/467848 在Java 线程中返回值的用法 博客分类: Java Javathread 有时在执行线程中需要在线程中返回一个值:常规中我们会用Runnable接口和Thread类设置一个变量:在run()中改变变量的值,再用一个get方法取得该值,但是run何时完成是未知的:我们需要一定的机制来保证. 在在Java se5有个Callable接口:我们可以用该接口来完成该功能: 代码如: Java代码   package com.thr

在子线程中更改主线程中的控件的信息,在子线程中用toast

一丶在子线程中不允许更改主线程中的控件的信息,也不允许在子线程中用toast,我们要更改的话 (1)消息机制:使用handler (由主线程调用) 在主程序中Handler handler = new Handler(){ public void handleMessage(Message msg){ int type = msg.what ;//拿到msg的类型,再判断            switch (type) {                case SUCCESS:      

业务代码中(java class)中如何实现多线程,并且将子线程中的值随方法返回返回值

转载自http://bbs.csdn.net/topics/390731832 问题: public static String getAddress(final InputStream inputStream, final String mobile) { new Thread() { public void run() { try { Log.i(TAG, "inputStream: " + inputStream.available()); String soap = readS

从返回的HTTP Header信息中隐藏Apache的版本号及PHP的X-Powered-By信息

默认情况下,很多apache安装时会显示版本号及操作系统版本,甚至会显示服务器上安装的是什么样的apache模块.这些信息可以为黑客所用,并且黑客还可以从中得知你所配置的服务器上的很多设置都是默认状态. 这里有两条语句,你需要添加到你的httpd.conf文件中:ServerSignature OffServerTokens Prod ServerSignature该参数设置 出现在apache所产生的像404页面.目录列表等页面的底部,三个选项 On|Off|EMai 主要起开关作用,推荐设置

android 不能在子线程中更新ui的讨论和分析

问题描述 做过android开发基本都遇见过ViewRootImpl$CalledFromWrongThreadException,上网一查,得到结果基本都是只能在主线程中更改ui,子线程要修改ui只能post到主线程或者使用handler之类.但是仔细看看exception的描述并不是这样的,"Only the original thread that created a view hierarchy can touch its views",只有创建该 view 布局层次的原始线程

利用objc的runtime来定位次线程中unrecognized selector sent to instance的问题

昨天遇到一个只有一行错误信息的问题: -[NSNull objectForKey:]: unrecognized selector sent to instance 0x537e068 由于这个问题发生在次线程,所以没有太有用的堆栈信息,而是只有简单的SIGABRT信息: 考虑到unrecognized selector sent to instance这类问题是由于向某个对象发送了未实现的消息,这个过程大致如下(图片摘自这里): 参考Objective-C的对象模型: struct objc_

模拟做饭系统(java+线程中的join方法)

(一)项目框架分析 妈妈要去做饭,发现没有酱油,让儿子去买酱油,然后回来做饭. 根据面向对象的思想,有两个对象,妈妈和儿子 主要有两个方法: (一)没有线程控制(即儿子没有买酱油回来妈妈就做好饭了)+(没有调用jion方法) (二)有线程控制(妈妈进程和儿子进程又先后影响)+(调用jion方法) 项目的结构图: (二)没有进程控制mintak Son.java主要是模拟儿子的行动,儿子买酱油的行动(与有进程控制的源程序相同) 代码如下: public class Son implements R