线程轮询和线程回调

当我们需要计算多个文件的消息摘要时,程序在单线程里执行是没问题的,不过相对用多线程处理起来,速度比较快,但多个线程处理完之后,我们怎么获取得线程执行的相关信息呢

我们知道通过执行Thread的start()就可以启动线程,而线程的任务是在run()中执行的。但线程执行结束后,我们该如何独得线程执行的信息呢?或许我们可以在线程类定义个方法,提供给线程的启动类调用,但是线程什么时候才执行完呢;另者,线程的run()执行完后主动将消息提供给启动类,这种方法比较有保障。

所以获取线程执行的信息有两个方法:

1、轮询

2、回调

一、轮询

在启动类里启动了线程后,启动类无限循环地去询问线程是否已经执行完。

private static String[] files = {
		"f:\\java.txt",
		"f:\\c.txt",
		"f:\\c++.txt",
		"f:\\javascript.txt",
		"f:\\html.txt"
	};
	
	private static DigestThread[] threads;
public static void main(String[] args) throws Exception{
		
		threads = new DigestThread[files.length];
		for(int i = 0 ; i < files.length ; i++){
			threads[i] = new DigestThread("F:\\" + files[i]);
			threads[i].start();
		}

                for(int j = 0 ; j < threads.length ; j++){
            byte[] message = null;
            while(true){
                message = threads[j].getDigest();
                if(message != null){
                    StringBuilder sb = new StringBuilder(threads[j].getFile().getAbsolutePath());
                    sb.append(":");
                    for(byte meg : message){
                        sb.append(meg);
                    }
                    System.out.println("polling " + sb.toString());
                    break;
                }
            }
        }
 }
DigestThread类:

public class DigestThread extends Thread{
	
	private File input;
	
	private byte[] message;
	
	public DigestThread(String fileName){
		this(new File(fileName));
	}
	
	public DigestThread(File input){
		this.input = input;
	}
	
	@Override
	public void run() {
		digest();
	}
	
	public void digest(){
		DigestInputStream din = null;
		try {
			FileInputStream in = new FileInputStream(input);
			MessageDigest sha = MessageDigest.getInstance("SHA");
			din = new DigestInputStream(in, sha);
			int b;
			while((b = din.read()) != -1);
			message = sha.digest();
		} catch (FileNotFoundException e) {
			System.err.println(e);
		} catch (NoSuchAlgorithmException e) {
			System.err.println(e);
		} catch (IOException e) {
			System.err.println(e);
		} catch (Exception e) {
			e.printStackTrace();
		} finally{
			try {
				if(din != null){
					din.close();
					din = null;
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
	
    public byte[] getDigest(){
    	return this.message;
    }
    
    public File getFile(){
    	return this.input;
    }

}

但在很多情况下,多次来询问线程时线程还没执行完,询问无功而返,这样就做了较多无用的操作。

二、回调

回调比轮询比较简单有效,不用再无限循环地询问线程是否执行完了。线程执行完后主动将消息告知启动类,那么启动类在线程执行过程中就可以休息,主要线程来通知它消息就可以了。

Callbackable:

public interface Callbackable {
	
	public void callback(byte[] bytes);

}
Calculatable:

public interface Calculatable {
	
	public void calculate();

}
CallbackListDigest:

线程类,将线程执行完后需要通知的启动类储放在列表callbacks中,这样设计可以通知不只一个类,所以需要知道线程执行的信息的类都添加到列表即可。

public class CallbackListDigest implements Runnable{
	
	private File file;
	
	private List<Callbackable> callbacks = new ArrayList<Callbackable>();
	
	public CallbackListDigest(File file) {
		this.file = file;
	}
	
	public void addCallback(Callbackable callback){
		callbacks.add(callback);
	}
	
	public void removeCallback(Callbackable callback){
		callbacks.remove(callback);
	}

	@Override
	public void run() {
		byte[] bytes = digest();
		sendDigest(bytes);
	}
	
	private byte[] digest(){
		DigestInputStream d = null;
		try {
			InputStream in = new FileInputStream(file);
			MessageDigest md = MessageDigest.getInstance("SHA");
			d = new DigestInputStream(in, md);
			int b;
			while( (b = d.read()) != -1);
			return md.digest();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally{
			try {
				if( d != null){
					d.close();
					d = null;
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return null;
	}
	
	private void sendDigest(byte[] bytes){
		Iterator<Callbackable> iterator = callbacks.iterator();
		while(iterator.hasNext()){
			iterator.next().callback(bytes);
		}
	}

}
CalculateInstance:

public class CalculateInstance implements Calculatable, Callbackable{
	
	private File file;
	
	public CalculateInstance(File file) {
		this.file = file;
	}

	@Override
	public void calculate() {
		CallbackListDigest d = new CallbackListDigest(file);
		d.addCallback(this);
		Thread thread = new Thread(d);
		thread.start();
	}

	@Override
	public void callback(byte[] bytes) {
		StringBuilder sb = new StringBuilder();
		sb.append(this.getClass().getSimpleName()).append(" ");
		sb.append(file.toString()).append(":");
		for(byte b : bytes){
			sb.append(b);
		}
		System.out.println(sb.toString());
	}

}
测试程序:

      for(int i = 0 ; i < files.length ; i++){
		        	 (new CalculateInstance(new File("F:\\" + files[i]))).calculate();
      }


  • 4
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值