记使用sevenzipjbinding多线程解压rar文件报错问题

发布于:2023-01-09 ⋅ 阅读:(713) ⋅ 点赞:(0)

一、问题

最近在开发过程中遇到一个问题,使用sevenzipjbinding解压文件报 SevenZipJBinding wasn’t initialized successfully last time 异常

使用一个简单的案例复现一下,注意:程序首次启动后,多个线程同时执行解压的方法才会出现

@RestController
@RequestMapping("/test")
@Slf4j
public class TestContortller {

    @GetMapping("/unRar")
    public void unRar() {
        String source = "D:\\temp\\test.rar";
        String target = "D:\\temp\\test\\";
        new Thread(() -> unRar(source, target + Thread.currentThread().getId())).start();
        new Thread(() -> unRar(source, target + Thread.currentThread().getId())).start();
        new Thread(() -> unRar(source, target + Thread.currentThread().getId())).start();
    }

    public static void unRar(String source, String target) {
        try (RandomAccessFile randomAccessFile = new RandomAccessFile(source, "r");
             IInArchive archive = SevenZip.openInArchive(null, new RandomAccessFileInStream(randomAccessFile))) {
            int[] in = new int[archive.getNumberOfItems()];
            for (int i = 0; i < in.length; i++) {
                in[i] = i;
            }
            archive.extract(in, false, new ExtractCallback(archive, target));
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
    }
}

在这里插入图片描述

二、原因

查看sevenzipjbinding源码发现,在调用解压方法的时候,先判断是否需要进行初始化, autoInitializationWillOccur 默认为true,当第一个线程进来此方法时,将autoInitializationWillOccur修改为false,然后初始化相关依赖(此操作需要一定的耗时),此时其他线程进来此方法,autoInitializationWillOccur已经变为false 就不再进行初始化,但是由于第一个线程还没有完成初始化操作initializationSuccessful还是为false,所以就会抛出SevenZipJBinding wasn’t initialized successfully last time异常

在这里插入图片描述

在这里插入图片描述

三、解决

使用ApplicationRunner在程序启动完成后,自动执行一下initSevenZipFromPlatformJAR方法,先将sevenzipjbinding需要的依赖完成初始化。

@Component
public class InitService implements ApplicationRunner {
    @Override
    public void run(ApplicationArguments args) throws Exception {
        SevenZip.initSevenZipFromPlatformJAR();
        log.info("初始化sevenzipjbinding相关依赖完成!");
    }
}