因为在大数据收集数据当中,若经常打开流关闭流,很多时间花在这上,此时可以使用池化+装饰模式来优化。
整个过程是这样的:用单例模式创建一个池,池里放的是通过装饰模式生成的FSDataOutputStream输出流对象,每当创建一个输出流对象,用完后不关闭。再根据下一个输出流路径判断将要创建的输出流对象是否跟上一个输出流对象一样,如果一样则不创建输出流对象,直接使用上一个输出流对象,如果不一样,则将上一个输出流对象关闭,放回池,然后创建新的输出流对象。然后创建一个守护进程,每隔一定时间清理。
首先创建装饰FSDataOutputStream类MyFSDataOutputStream:
/** *装饰流 */ public class MyFSDataOutputStream extends FSDataOutputStream{ private String path ; private FSDataOutputStream out ; private HDFSOutputStreamPool pool ;//池 public MyFSDataOutputStream(String path , FSDataOutputStream out, HDFSOutputStreamPool pool) throws IOException{ super(null); this.out = out ; this.pool = pool ; this.path=path; } public void close(){ try{ out.close(); } catch(Exception e){ e.printStackTrace(); } } public void hflush() throws IOException { out.hflush(); } public void write(byte[] b) throws IOException { out.write(b); } public void hsync() throws IOException { out.hsync(); } /** * 回收,放入池 */ public void release(){ pool.putBack(path, this); } }
HDFSOutputStreamPool类:
package com.chenway.kafkaconsumer; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.FSDataOutputStream; import org.apache.hadoop.fs.FileSystem; import org.apache.hadoop.fs.Path; import java.io.IOException; import java.util.HashMap; import java.util.Map; /* 输出流池 */ public class HDFSOutputStreamPool { private FileSystem fs; //存放所有的输出流 private Map<String, FSDataOutputStream> pool = new HashMap<String, FSDataOutputStream>(); private static HDFSOutputStreamPool instance; private HDFSOutputStreamPool() { try { Configuration configuration = new Configuration(); fs = FileSystem.get(configuration); } catch (Exception e) { e.printStackTrace(); } } //单例设计模式 public static HDFSOutputStreamPool getInstance() { if (instance == null) { instance = new HDFSOutputStreamPool(); } return instance; } public synchronized FSDataOutputStream takeOutputStream(String path) { try { FSDataOutputStream out = pool.remove(path); if (out == null) { Path p = new Path(path); if (!fs.exists(p)) { //若不存在就创建 fs.createNewFile(p); } out = fs.append(p);//存在则直接追加 } return new MyFSDataOutputStream(path,out,this); } catch (IOException e) { e.printStackTrace(); } return null; } public synchronized void putBack(String path,FSDataOutputStream fsDataOutputStream){ pool.put(path,fsDataOutputStream); } public synchronized void releasePool(){ try { for (FSDataOutputStream out :pool.values()) { out.close(); } pool.clear(); System.out.println("池释放!!"); } catch (IOException e) { e.printStackTrace(); } } }
创建一个守护进程清理池TimerTask:
package com.chenway.kafkaconsumer; import java.util.TimerTask; /* 关闭线程池 */ public class CloseFSOutputStreamTask extends TimerTask { public void run() { HDFSOutputStreamPool pool = HDFSOutputStreamPool.getInstance(); pool.releasePool(); } }
导出jar包:
①通过mvn命令,使用依赖方式下载运行的所有第三包,在当前模块中的pom.xml文件路径下:
mvn -DoutputDirectory=./lib -DgroupId=com.chenway -DartifactId=EshopConsumer -Dversion=1.0-SNAPSHOT dependency:copy-dependencies
②将产生项目jar到lib下.
③在centos上使用xargs处理文本
$>ls | xargs > a.txt
④将替换所有空格 -> :
vim a.txt
然后输入:s/ /:/g 将空格全部替换为:
再在a.txt后面添加com.chenway.kafkconsumer.HDFSRawConsumer
再在前面添加java -cp
⑤复制a.txt中的内容,将以命令行方式输入
每隔30s释放一次池: