多线程环境下Java怎么从线程返回信息?

1. 问题描述

习惯了传统单线程过程式模型的程序员在转向多线程环境时,最难掌握的一点就是如何从线程返回信息。从结束的线程获得信息,这是多线程编程中最常被误解的方面之一。run()方法和start()方法不返回任何值。

2. 使用存储方法返回结果

如下面程序

public class QuizCardBuilder {
    public static void main(String[] args) throws InterruptedException {
        ReturnDigest dr=new ReturnDigest("foo.ser");
        dr.start();
        dr.join();
        StringBuilder re=new StringBuilder("foo.ser");
        re.append(": ");
        byte[] digest=dr.getDigest();
        re.append(DatatypeConverter.printHexBinary(digest));
        System.out.println(re);
    }
}
class ReturnDigest extends Thread{
    private String filename;
    private byte[] digest;

    public ReturnDigest(String filename){
        this.filename=filename;
    }

    public byte[] getDigest() {
        return digest;
    }

    @Override
    public void run(){
        try{
            FileInputStream in=new FileInputStream(filename);
            MessageDigest sha=MessageDigest.getInstance("SHA-256");
            DigestInputStream din=new DigestInputStream(in ,sha);
            while(din.read()!=-1){//读取文件的信息
            }
            din.close();
            digest=sha.digest();
        }catch (IOException | NoSuchAlgorithmException e){
            e.printStackTrace();
        }
    }

}

子线程的的作用是计算文件的SHA-256哈希值。解释如下:

  • 首先,使用FileInputStream类创建一个输入流in,用于读取指定文件filename的内容。
  • 接下来,通过MessageDigest.getInstance(“SHA-256”)获取一个SHA-256的MessageDigest对象sha,用于计算哈希值。
  • 然后,创建一个DigestInputStream对象din,将输入流in和sha对象传递给它。DigestInputStream是一个过滤流,它可以在数据流中进行数据处理,并计算哈希值。
  • 在一个循环中,通过din.read()不断读取文件的数据,直到文件的末尾(返回值为-1)。这个循环的目的是将文件的内容传递给DigestInputStream,使其能够计算哈希值。
  • 读取完成后,关闭DigestInputStream,调用din.close()。
  • 最后,通过sha.digest()获取计算得到的SHA-256哈希值的字节数组,并将其赋值给变量digest。

通过上述代码,文件的内容会被逐个字节地读取并传递给DigestInputStream,而DigestInputStream会将这些数据输入到MessageDigest对象sha中进行处理。在循环结束后,通过调用sha.digest()获取最终的SHA-256哈希值。你可以使用该哈希值进行进一步的验证、比对或存储,以确保文件的完整性或进行其他安全相关的操作。最后程序也确实获取了线程的操作结果:
但上面程序存在一个很大的问题,由于调用了join主线程一直阻塞在这里,这样程序的效率是很不高的,所以我们介绍一种更好的方法,即回调机制

3. 回调机制

该机制是通过调用主类(即启动子线程的类)中的一个方法来做到的。这种被称为回调(CallBack),因为线程在完成时反过来调用其创建者。这样依赖,主程序就可以在等待线程结束期间休息,而不会占用运行线程的时间。

public class QuizCardBuilder {
    public static void receiveDigest(byte[] digest,String name){
        StringBuilder re=new StringBuilder(name);
        re.append(": ");
        re.append(DatatypeConverter.printHexBinary(digest));
        System.out.println(re);
    }
    public static void main(String[] args) throws InterruptedException {
        ReturnDigest re=new ReturnDigest("foo.ser");
        Thread t=new Thread(re);
        t.start();
    }
}
class ReturnDigest extends Thread{
    private String filename;
    private byte[] digest;

    public ReturnDigest(String filename){
        this.filename=filename;
    }

    public byte[] getDigest() {
        return digest;
    }

    @Override
    public void run(){
        try{
            FileInputStream in=new FileInputStream(filename);
            MessageDigest sha=MessageDigest.getInstance("SHA-256");
            DigestInputStream din=new DigestInputStream(in ,sha);
            while(din.read()!=-1){//读取文件的信息
            }
            din.close();
            digest=sha.digest();
            QuizCardBuilder.receiveDigest(digest,filename);
        }catch (IOException | NoSuchAlgorithmException e){
            e.printStackTrace();
        }
    }
}

上面使用静态方法完成了回调

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值