在我们工作的项目中,每个项目都会涉及到操作日志,每个公司当然也有自己的想法自己做操作日志的保存。我今天造了一个简单的轮子来写日志。采用的技术是Executors跟BlockingQueue。
一个线程池接口,定义了一个可以接收Runnable对象的方法executor,该方法接收要给Runnable实例后,可以用来执行一个任务,一般使用execute(new RunnableTask())方法异步执行。
为什么要开另外一个线程?
为什么要异步执行?因为这里考虑到操作日志不应该影响到我们的性能,我们在操作之后,无需等到日志写完才response。
Blocking 即为阻塞,Queue即为队列,BlockingQueue阻塞队列类。
其实就是一个队列的数据结构,线程一直以队列的数据结构从BlockingQueue里面拿数据,如果没数据了,那么线程就一直阻塞进入等待状态,一直等一直等,直到有其他线程在BlockingQueue中添加了数据,被阻塞的线程被唤醒。同样,如果BlockingQueue是满的,有线程从队列中存放数据,线程也会被阻塞,一直等一直等,等到不满的时候,线程唤醒,继续存放数据。
操作内容
package com.zero.na;
import java.util.Map;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class WriteLogUtil {
private ExecutorService executorService;
private BlockingQueue<Map<String, String>> bqBuff;
public WriteLogUtil() {
executorService = Executors.newSingleThreadExecutor();
bqBuff = new ArrayBlockingQueue<>(1024);
executorService.execute(new Runnable() {
@Override
public void run() {
while (true) {
Map<String, String> item = null;
try {
item = bqBuff.take();
} catch (InterruptedException e) {
e.printStackTrace();
}
if (item != null) {
write(item);
}
}
}
});
}
private final static WriteLogUtil instance = new WriteLogUtil();
public static WriteLogUtil getInstance() {
return instance;
}
public void appLog(Map<String, String> log) {
saveLog(log);
}
private void saveLog(Map<String, String> log) {
bqBuff.add(log);
}
private void write(Map<String, String> item) {
System.out.println(item);
}
}
测试1
package com.zero.na;
import java.util.HashMap;
import java.util.Map;
public class Test1 {
public static void main(String[] args) {
WriteLogUtil instance = WriteLogUtil.getInstance();
Map<String, String> map = new HashMap<>();
map.put("name", "zero");
map.put("detail", "第一个客户支付了十块钱");
instance.appLog(map);
}
}
测试2
package com.zero.na;
import java.util.HashMap;
import java.util.Map;
public class Test2 {
public static void main(String[] args) {
WriteLogUtil instance = WriteLogUtil.getInstance();
Map<String, String> map = new HashMap<>();
map.put("name", "zero");
map.put("detail", "第二个客户支付了二十块钱");
instance.appLog(map);
}
}
我们可以看到这个线程永远都不会停止,因为我们会有一个线程一直在while(true),一直在执行,永远都在等待。这个时候我们的用例写好了。这个时候我们的日志可以选择写在MongoDB数据库中。
这个我们下篇讲。。。。。。