JAVA 实现简单的日志工具

因为需求有点变化,原来需要写入数据库的数据现在变为把json字符串写到文档,本来使用logback轻松可以做到日志写入,但是上面说需要自己写。

需求比较简单,在rest服务调用写文件接口,当文件大小超过定值时,新建文件进行存储。

开始我采用的方式是每次调用都会实例一个File,对文件进行写操作,完成后进行关闭,但是rest服务后期会做压力测试,当很多请求写同一个文件时,最后程序卡死了,所以最后想采用一个专门线程对单一文件进行写,所以需要在内存中申请一块内存,调用文件写接口将数据放入内存,然后线程将内存中数据写到文件。

为了提高写入内存,和从内存读取数据落地操作的并发性,我申请了两块内存,一块专门进行写,一块进行读取落地,当写入内存满滞后,进行两块内存作业的切换。后来考虑到采用当内存满才进行写入操作的方式,可能当程序发生错误时,会将很大一部分内存中的数据都丢失掉,所以我有参考oracle日志线程的功能,添加了定时落地功能,在内存满或者定时器时间到达时进行数据落地,具体代码如下,以供参考。

package com.liwe.commons;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

import org.springframework.stereotype.Service;

@Service
public class FileBufferWrite implements Runnable {
	final static long filesize=1024;
	final int size = 1024;
	byte[] cache1 = new byte[size];
	byte[] cache2 = new byte[size];
	Object lockr = new Object();
	Thread thd = null;
	FileBufferWrite ptr = this;
	FileOutputStream fos;
	int pos = 0;
	int cacheforuse = 1;
	long filelen=0;
	int writting = 0;
	int lastlen=0;
	String pathName;
	public String getPathName() {
		return pathName;
	}


	public void setPathName(String pathName) {
		this.pathName = pathName;
	}

	File file=new File(pathName+"log.txt");
	public FileBufferWrite() {
	
	}


	public void switchcache() {
		if (pos != 0) {
			System.out.println("switch cache");
			cacheforuse = 1 - cacheforuse;
			lastlen=pos;
			pos = 0;
			synchronized (lockr) {
				lockr.notify();
			}
		}
	}

	public Thread getThread() {
		Thread thd = new Thread(this);
		thd.start();
		new Thread(new Runnable() {
			public void run() {
				while (true) {
					try {
						Thread.sleep(1000);
						synchronized (ptr) {
							while (writting == 1) {
								Thread.sleep(100);
							}
							switchcache();

						}
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}

				}
			}
		}).start();
		return thd;
	}

	public void run() {
		try {
			while (true) {
				synchronized (lockr) {
					lockr.wait();
				}
				writting = 1;
				System.out.println("start write file from cache" + cacheforuse);
				try {
					byte[] bfw;
					bfw=new byte[lastlen];
					if (cacheforuse == 1) {
						System.arraycopy(cache2, 0,bfw, 0,lastlen);
					} else {
						System.arraycopy(cache1, 0,bfw, 0,lastlen);
					}
					try {
						file=new File(pathName+"log.txt");
						if(!file.getParentFile().exists())
							file.getParentFile().mkdirs();
						if(!file.exists())
							file.createNewFile();
							fos = new FileOutputStream(file);

					} catch (Exception e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					if(filelen+lastlen>filesize){
						
						File[] fl=new File(pathName).listFiles();
						int num=fl.length;
						fos.close();
						file.renameTo(new File(pathName+"log"+num+".txt"));
				
						file=new File(pathName+"log.txt");
						fos=new FileOutputStream(file);
						filelen=0;
						System.out.println("change file");
					}
					fos.write(bfw);
					fos.flush();
					filelen+=lastlen;
				
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				System.out.println("file write over");
				writting = 0;
			}

		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public synchronized void write(String str) throws InterruptedException {
		if (thd == null) {
			thd = getThread();
		}
		str+="\r\n";
		byte[] tmp = str.getBytes();
		if (pos + tmp.length > size) {
			System.out.println("cache filled");
			while (writting == 1) {
				System.out.println("sleeping");
				Thread.sleep(10);
			}
			switchcache();

			System.out.println("notify");

		}
		System.out.println("cache write");
		if (cacheforuse == 1) {
			System.arraycopy(tmp, 0, cache1, pos, tmp.length);
			pos += tmp.length;
		} else {
			System.arraycopy(tmp, 0, cache2, pos, tmp.length);
			pos += tmp.length;
		}
	}
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值