java Future接口在logback的妙用

logback可以把N天的日志压缩成一个包(zip,gz),在压缩的时候logback采用后台异步线程的方式来实现,下面咱们就来看看Future接口在logback中的妙用。

先来看下Future接口的全貌吧。

1public interface Future<V> { 2 3 //取消任务 4 boolean cancel(boolean mayInterruptIfRunning); 5 6 // 任务如果被取消就返回true 7 boolean isCancelled(); 8 9 //如果任务完成就返回true 10 boolean isDone(); 11 // 获取线程的执行结果,如果任务没有执行完成就会一直等待 12 V get() throws InterruptedException, ExecutionException; 13 14 //获取任务的执行结果,可以指定一个单位时间,如果在规定的时间内没有完成任务,那么就会抛出TimeoutException异常 15 V get(long timeout, TimeUnit unit) 16 throws InterruptedException, ExecutionException, TimeoutException; 17 18 19 20 21 22 23/** 24 gz压缩方法,用于压缩成.gz文件 25*/ 26 private void gzCompress(String nameOfFile2gz, String nameOfgzedFile) { 27 File file2gz = new File(nameOfFile2gz); 28 29 if (!file2gz.exists()) { 30 addStatus(new WarnStatus("The file to compress named [" + nameOfFile2gz + "] does not exist.", this)); 31 32 return; 33 } 34 35 if (!nameOfgzedFile.endsWith(".gz")) { 36 nameOfgzedFile = nameOfgzedFile + ".gz"; 37 } 38 39 File gzedFile = new File(nameOfgzedFile); 40 41 if (gzedFile.exists()) { 42 addWarn("The target compressed file named [" + nameOfgzedFile + "] exist already. Aborting file compression."); 43 return; 44 } 45 46 addInfo("GZ compressing [" + file2gz + "] as [" + gzedFile + "]"); 47 createMissingTargetDirsIfNecessary(gzedFile); 48 49 BufferedInputStream bis = null; 50 GZIPOutputStream gzos = null; 51 try { 52 bis = new BufferedInputStream(new FileInputStream(nameOfFile2gz)); 53 gzos = new GZIPOutputStream(new FileOutputStream(nameOfgzedFile)); 54 byte[] inbuf = new byte[BUFFER_SIZE]; 55 int n; 56 57 while ((n = bis.read(inbuf)) != -1) { 58 gzos.write(inbuf, 0, n); 59 } 60 61 bis.close(); 62 bis = null; 63 gzos.close(); 64 gzos = null; 65 66 if (!file2gz.delete()) { 67 addStatus(new WarnStatus("Could not delete [" + nameOfFile2gz + "].", this)); 68 } 69 } catch (Exception e) { 70 addStatus(new ErrorStatus("Error occurred while compressing [" + nameOfFile2gz + "] into [" + nameOfgzedFile + "].", this, e)); 71 } finally { 72 if (bis != null) { 73 try { 74 bis.close(); 75 } catch (IOException e) { 76 // ignore 77 } 78 } 79 if (gzos != null) { 80 try { 81 gzos.close(); 82 } catch (IOException e) { 83 // ignore 84 } 85 } 86 } 87 } 88 89 90 //工厂方法,可以根据传入的类型来判断是使用gz,还是zip压缩 91 public void compress(String nameOfFile2Compress, String nameOfCompressedFile, String innerEntryName) { 92 switch (compressionMode) { 93 case GZ: 94 gzCompress(nameOfFile2Compress, nameOfCompressedFile); 95 break; 96 case ZIP: 97 zipCompress(nameOfFile2Compress, nameOfCompressedFile, innerEntryName); 98 break; 99 case NONE: 100 throw new UnsupportedOperationException("compress method called in NONE compression mode"); 101 } 102 } 103 104 105 106 107 108

logback 把压缩的任务交给了一个线程去执行

1 //开启一个线程用于压缩日志文件 2 public Future<?> asyncCompress(String nameOfFile2Compress, String nameOfCompressedFile, String innerEntryName) throws RolloverFailure { 3 CompressionRunnable runnable = new CompressionRunnable(nameOfFile2Compress, nameOfCompressedFile, innerEntryName); 4 ExecutorService executorService = context.getExecutorService(); 5 Future<?> future = executorService.submit(runnable); 6 return future; 7 } 8 9 //压缩线程 10 class CompressionRunnable implements Runnable { 11 final String nameOfFile2Compress; 12 final String nameOfCompressedFile; 13 final String innerEntryName; 14 15 public CompressionRunnable(String nameOfFile2Compress, String nameOfCompressedFile, String innerEntryName) { 16 this.nameOfFile2Compress = nameOfFile2Compress; 17 this.nameOfCompressedFile = nameOfCompressedFile; 18 this.innerEntryName = innerEntryName; 19 } 20 21 public void run() { 22 Compressor.this.compress(nameOfFile2Compress, nameOfCompressedFile, innerEntryName); 23 } 24 } 25 26 27

stop方法才是重头戏,当调用stop方法的时候,需要检查有没有线程在正在进行压缩工作,可以看出logback使用Future的特性就是检测某个后台任务是否在指定时间内完成任务。

1 @Override 2 public void stop() { 3 if (!isStarted()) 4 return; 5 //检查任务是否完成 6 //压缩任务 7 waitForAsynchronousJobToStop(compressionFuture, "compression"); 8 //clean任务 9 waitForAsynchronousJobToStop(cleanUpFuture, "clean-up"); 10 super.stop(); 11 } 12 13 private void waitForAsynchronousJobToStop(Future<?> aFuture, String jobDescription) { 14 if (aFuture != null) { 15 try { 16 //获取执行结果 17 aFuture.get(CoreConstants.SECONDS_TO_WAIT_FOR_COMPRESSION_JOBS, TimeUnit.SECONDS); 18 } catch (TimeoutException e) { 19 addError("Timeout while waiting for " + jobDescription + " job to finish", e); 20 } catch (Exception e) { 21 addError("Unexpected exception while waiting for " + jobDescription + " job to finish", e); 22 } 23 } 24 }
点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

2020年前端实用代码段,为你的工作保驾护航

有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )