All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.alibaba.jvm.sandbox.api.http.printer.ConcurrentLinkedQueuePrinter Maven / Gradle / Ivy

There is a newer version: 1.4.0
Show newest version
package com.alibaba.jvm.sandbox.api.http.printer;

import java.io.PrintWriter;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 高性能文本输出
 * 高性能背后的代价就是相对比较高的CPU开销
 *
 * @author [email protected]
 */
public class ConcurrentLinkedQueuePrinter implements Printer {

    private static final String NUL_STRING = new String(new byte[]{0x00});
    private final PrintWriter writer;
    private final ConcurrentLinkedQueue writeQueue;
    private final ReentrantLock lock = new ReentrantLock();
    private final Condition condition = lock.newCondition();
    private final int capacity;

    // 是否被打断
    private final AtomicBoolean isBrokenRef = new AtomicBoolean(false);

    private final long delayStepTimeMs;
    private final long delayMaxTimeMs;
    private volatile long delayTimeMs;

    /**
     * 构造文本输出
     *
     * @param writer          {@link PrintWriter}
     * @param delayStepTimeMs 轮空延时步长(单位毫秒)
     *                        Printer会每隔这个时间间隔检查是否有输出,如果没有任何输出则会延时累加,
     *                        整体累加延时不会超过{@link #delayMaxTimeMs}
     * @param delayMaxTimeMs  最大轮空延时
     * @param capacity        队列最大容量
     *                        超过最大容量的输入将会被主动丢弃
     */
    public ConcurrentLinkedQueuePrinter(final PrintWriter writer,
                                        final long delayStepTimeMs,
                                        final long delayMaxTimeMs,
                                        final int capacity) {
        this.writer = writer;
        this.writeQueue = new ConcurrentLinkedQueue();
        this.delayStepTimeMs = delayStepTimeMs;
        this.delayMaxTimeMs = delayMaxTimeMs;
        this.delayTimeMs = delayStepTimeMs;
        this.capacity = capacity;
    }

    /**
     * 构造文本输出
     * 
    *
  • {@code delayStepTimeMs}=20
  • *
  • {@code delayMaxTimeMs}=200
  • *
  • {@link Integer#MAX_VALUE}
  • *
* * @param writer {@link PrintWriter} */ public ConcurrentLinkedQueuePrinter(final PrintWriter writer) { this(writer, 20, 200, Integer.MAX_VALUE); } private boolean isOverCapacity() { return writeQueue.size() >= capacity; } @Override public Printer print(String string) { if (!isOverCapacity()) { writeQueue.offer(string); } return this; } @Override public Printer println(String string) { if (!isOverCapacity()) { writeQueue.offer(string + "\n"); } return this; } private void commit() { while (!writeQueue.isEmpty()) { final String string = writeQueue.poll(); if (null == string) { writer.print(NUL_STRING); } else { writer.print(string); } } } @Override public Printer flush() { commit(); writer.flush(); return this; } private long computeDelayTimeMs() { if (delayTimeMs >= delayMaxTimeMs) { return delayTimeMs; } else { final long newDelayTime = delayTimeMs + delayStepTimeMs; delayTimeMs = newDelayTime < delayMaxTimeMs ? newDelayTime : delayMaxTimeMs; return delayTimeMs; } } private long resetDelayTimeMs() { return delayTimeMs = delayStepTimeMs; } private void delay() throws InterruptedException { // 如果最大延时时间不为正数,说明不要延时 if (delayMaxTimeMs <= 0) { return; } lock.lock(); try { condition.await(computeDelayTimeMs(), TimeUnit.MILLISECONDS); } finally { lock.unlock(); } } @Override public Printer waitingForBroken() { waitingForBroken(0L, TimeUnit.MILLISECONDS); return this; } @Override public boolean waitingForBroken(final long time, final TimeUnit unit) { // 超时等待时间 final long timeMs = unit.toMillis(time); // 是否需要进行超时控制 final boolean isTimeoutControl = timeMs > 0; // 方法执行开始时间(超时等待计时开始) final long startMs = isTimeoutControl ? System.currentTimeMillis() : 0; try { int heartBeat = 0; while (!writer.checkError() && !isBrokenRef.get() && !Thread.currentThread().isInterrupted()) { if (isTimeoutControl && System.currentTimeMillis() - startMs >= timeMs) { return true; } if (writeQueue.isEmpty()) { delay(); if (heartBeat++ > 20) { heartBeat = 0; writer.write(0x0); } } else { flush(); resetDelayTimeMs(); } } } catch (InterruptedException e) { Thread.currentThread().interrupt(); flush(); } catch (Throwable cause) { // maybe IOException } return false; } @Override public Printer broken() { isBrokenRef.set(true); return this; } @Override public boolean isBroken() { return isBrokenRef.get(); } @Override public void close() { writeQueue.clear(); if (null != writer) { try { writer.close(); } catch (Throwable cause) { // ignore... } } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy