Java 多线程解压文件
2020-12-07 本文已影响0人
贼噶人
private static AtomicBoolean isMThreadUnZip = new AtomicBoolean(true);
private static ListeningExecutorService unzipExecutor = MoreExecutors
.listeningDecorator(new ThreadPoolExecutor(2,
Math.max(Runtime.getRuntime().availableProcessors() - 2, 2), 15,
TimeUnit.SECONDS,
new LinkedBlockingQueue<Runnable>()));
public static abstract class UnzipListener {
public abstract void success();
public void onUnzip(float progress) {
}
public void fail(String message) {
}
}
static class UnZipCallable implements Callable<Boolean> {
private InputStream zipInputStream;
private File target;
private BufferedSink sink;
private BufferedSource source;
public UnZipCallable(final InputStream zipInputStream, final File target) {
this.zipInputStream = zipInputStream;
this.target = target;
}
@Override
public Boolean call() throws Exception {
try {
sink = Okio.buffer(okio.Okio.sink(target));
source = Okio.buffer(Okio.source(zipInputStream));
source.readAll(sink);
sink.flush();
return true;
} finally {
close(source);
close(sink);
}
}
}
/**
* 多线程解压文件
* @param file
* @param targetDir
* @param clear
* @param listener
*/
public static void unzipByMThread(File file, File targetDir, boolean clear,
final UnzipListener listener) {
if (clear) {
clearDir(targetDir);
//以前是Libgdx课程,现在是Unity的删除老的Libgdx课程下载
if (!targetDir.getAbsolutePath().contains(File.separator + "common")
&& targetDir.getAbsolutePath().contains(File.separator + "unity" + File.separator)) {
clearDir(new File(targetDir.getAbsolutePath().replace("unity"
+ File.separator, "")));
}
}
if (!targetDir.exists()) {
if (!targetDir.mkdirs()) {
if (null != listener) {
listener.fail("创建目录失败");
}
return;
}
}
final String targetPath = targetDir.getAbsolutePath() + File.separator;
ZipFile zip = null;
try {
zip = new ZipFile(file);
final Enumeration<? extends ZipEntry> entries = zip.entries();
final int size = zip.size();
final AtomicInteger current = new AtomicInteger(0);
final AtomicBoolean isException = new AtomicBoolean(false);
final CountDownLatch countDownLatch = new CountDownLatch(size);
final ZipFile hZip = zip;
try {
while (!isException.get() && entries.hasMoreElements()) {
final ZipEntry entry = entries.nextElement();
final File target = new File(targetPath + entry.getName());
if (entry.isDirectory()) {
if (!target.exists()) {
target.mkdirs();
}
current.incrementAndGet();
if (null != listener) {
listener.onUnzip(1f * current.get() / size);
}
countDownLatch.countDown();
continue;
} else if (!target.exists()) {
if (!target.getParentFile().exists()) {
target.getParentFile().mkdirs();
}
}
Futures.addCallback(unzipExecutor.submit(new UnZipCallable(hZip.getInputStream(entry)
, target)), new FutureCallback<Boolean>() {
@Override
public void onSuccess(final Boolean result) {
current.incrementAndGet();
if (null != listener) {
listener.onUnzip(1f * current.get() / size);
}
countDownLatch.countDown();
}
@Override
public void onFailure(Throwable throwable) {
isException.set(true);
isMThreadUnZip.set(false);
while (countDownLatch.getCount() > 0) {
countDownLatch.countDown();
}
}
});
}
} catch (final Exception e) {
isException.set(true);
isMThreadUnZip.set(false);
while (countDownLatch.getCount() > 0) {
countDownLatch.countDown();
}
}
countDownLatch.await(5, TimeUnit.MINUTES);
if (isException.get()) {
throw new Exception("Unzip Exception");
}
if (null != listener) {
listener.onUnzip(1f);
listener.success();
}
}
catch (Exception e)
{
try {
if (e instanceof ZipException
&& (e.getMessage().contains("File too short to")
|| 0 == file.length())) {
ClazzObservable.getInstance().notifyObservers();
}
} catch (Exception ex) {
}
clearDir(targetDir);
if (null != listener)
{
listener.fail("解压失败:" + e.getClass().getSimpleName());
}
try
{
Platform.get().getAppManager().putUmAgent(Gdx.app, new Exception(targetDir + "#"
+ e.getMessage(), e));
}
catch (Exception ex)
{
}
}
finally
{
if (null != zip && zip instanceof Closeable)
{
close(zip);
}
}
}