@Test privatevoidtest4(){ long l = System.currentTimeMillis(); for (int i = 0; i 20000; i++) { log.info(i+""); } System.out.println("打印日志耗时:" + (System.currentTimeMillis() - l)); }
publicstaticvoidmain(String[] args){ long l = System.currentTimeMillis(); ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(10, 10, 60, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(20000)); for (int i = 0; i 20000; i++) { threadPoolExecutor.execute(new Runnable() { @Override publicvoidrun(){
//com.lmax.disruptor.dsl.Disruptor#handleEventsWith(com.lmax.disruptor.EventHandler super T>...) //添加事件处理(消费者) publicfinal EventHandlerGrouphandleEventsWith(final EventHandler super T>... handlers){ return createEventProcessors(new Sequence[0], handlers); }
//com.lmax.disruptor.dsl.Disruptor#createEventProcessors(com.lmax.disruptor.Sequence[], com.lmax.disruptor.EventHandler super T>[]) //创建事件处理(消费对象) EventHandlerGroupcreateEventProcessors( final Sequence[] barrierSequences, final EventHandler super T>[] eventHandlers){ //.... //所有消费者的Sequence final Sequence[] processorSequences = new Sequence[eventHandlers.length]; //将生产者包装成为SequenceBarrier final SequenceBarrier barrier = ringBuffer.newBarrier(barrierSequences); //遍历事件处理 for (int i = 0, eventHandlersLength = eventHandlers.length; i final EventHandler super T> eventHandler = eventHandlers[i]; //创建事件处理(消费者) final BatchEventProcessor batchEventProcessor = new BatchEventProcessor<>(ringBuffer, barrier, eventHandler); //.... //将消费者的Sequence放入gatingSequences中 processorSequences[i] = batchEventProcessor.getSequence(); } //更新生产者的processorSequences updateGatingSequencesForNextInChain(barrierSequences, processorSequences); //.... }
//org.apache.logging.log4j.core.async.AsyncLoggerConfig#logToAsyncDelegate privatevoidlogToAsyncDelegate(final LogEvent event){ if (!isFiltered(event)) { // Passes on the event to a separate thread that will call // asyncCallAppenders(LogEvent). populateLazilyInitializedFields(event); //尝试将logevnet对象发布到环形数组中 if (!delegate.tryEnqueue(event, this)) { //如果没有放进去,说明队列满了,执行队列满的处理方法,本质上类似于线程池队列满丢弃策略 //ENQUEUE:将日志放入环形数组(放入不进去就循环等待,一直到放进去) //SYNCHRONOUS:当前线程打印日志 //DISCARD:直接丢弃,忽略日志 handleQueueFull(event); } } }
//org.apache.logging.log4j.util.StackLocator#calcLocation public StackTraceElement calcLocation(final String fqcnOfLogger){ //.... //fqcnOfLogger=org.apache.logging.slf4j.Log4jLogger //获取当前方法调用链路上所有的调用链路 final StackTraceElement[] stackTrace = new Throwable().getStackTrace(); boolean found = false; for (int i = 0; i final String className = stackTrace[i].getClassName(); //判断类名称是否相同 if (fqcnOfLogger.equals(className)) {
found = true; continue; } //这样就得到了谁调用的日志输出了 if (found && !fqcnOfLogger.equals(className)) { return stackTrace[i]; } } returnnull; } //java.lang.Throwable#getStackTrace public StackTraceElement[] getStackTrace() { return getOurStackTrace().clone(); } //java.lang.Throwable#getOurStackTrace privatesynchronized StackTraceElement[] getOurStackTrace() { // Initialize stack trace field with information from // backtrace if this is the first call to this method if (stackTrace == UNASSIGNED_STACK || (stackTrace == null && backtrace != null) /* Out of protocol state */) { //获取调用链路的长度 int depth = getStackTraceDepth(); stackTrace = new StackTraceElement[depth]; for (int i=0; i //获取每一级调用链路 stackTrace[i] = getStackTraceElement(i); } elseif (stackTrace == null) { return UNASSIGNED_STACK; } return stackTrace; } //方法都是本地方法 nativeintgetStackTraceDepth(); native StackTraceElement getStackTraceElement(int index);
//org.apache.logging.log4j.util.StackLocator#calcLocation public StackTraceElement calcLocation(final String fqcnOfLogger){ //.... //fqcnOfLogger=org.apache.logging.slf4j.Log4jLogger //将这里改为自己的写的方法调用,构建方法调用链路 final StackTraceElement[] stackTrace = stackTraceElements(fqcnOfLogger); boolean found = false; for (int i = 0; i final String className = stackTrace[i].getClassName(); //判断类名称是否相同 if (fqcnOfLogger.equals(className)) {
found = true; continue; } //这样就得到了谁调用的日志输出了 if (found && !fqcnOfLogger.equals(className)) { return stackTrace[i]; } } returnnull; } /** * 构建stackTraceElement数组 * @param fqcnOfLogger * @return */ private StackTraceElement[] stackTraceElements(String fqcnOfLogger) { //构建一个42长度的,保持测试代码获取相同长度的方法调用链路 int size = 42; StackTraceElement[] stackTraceElement = new StackTraceElement[size]; for (int i = 0; i 2; i++) { stackTraceElement[i] = new StackTraceElement("1", "1", "1", 1); } stackTraceElement[size - 2] = new StackTraceElement(fqcnOfLogger, "1", "1", 1); stackTraceElement[size - 1] = new StackTraceElement("1", "1", "1", 1); return stackTraceElement; }
//然后再执行代码测试代码 @Test privatevoidtest4(){ long l = System.currentTimeMillis(); for (int i = 0; i 20000; i++) { log.info(i+""); } System.out.println("打印日志耗时:" + (System.currentTimeMillis() - l)); }