class WebSocketTimeoutBase extends WebSocketBase {

    private long idleTimeout;
    private ScheduledFuture<?> idleTimeoutFuture;
    private long liveTime;
    private final ReentrantLock SYNC_LOCK = new ReentrantLock(true);

    /**
     * 当发送时
     */
    public void onSend() {
        liveTime = System.currentTimeMillis();
    }

    /**
     * 当接收时
     */
    public void onReceive() {
        liveTime = System.currentTimeMillis();
    }

    @Override
    public long getIdleTimeout() {
        return idleTimeout;
    }

    @Override
    public void setIdleTimeout(long idleTimeout) {
        this.idleTimeout = idleTimeout;
        this.liveTime = System.currentTimeMillis();

        checkIdleTimeoutFuture();
    }

    private void checkIdleTimeoutFuture() {<FILL_FUNCTION_BODY>}
}

        SYNC_LOCK.lock();
        try {
            if (idleTimeout > 0) {
                if (liveTime + idleTimeout < System.currentTimeMillis()) {
                    if (this.isValid()) {
                        if (log.isDebugEnabled()) {
                            log.debug("WebSocket idle timeout, will close!");
                        }

                        RunUtil.runAndTry(this::close);
                        WebSocketRouter.getInstance().getListener().onClose(this);
                        return;
                    }
                }

                if (idleTimeoutFuture != null) {
                    idleTimeoutFuture.cancel(true);
                }

                idleTimeoutFuture = RunUtil.delay(this::checkIdleTimeoutFuture, idleTimeout);
            } else {
                if (idleTimeoutFuture != null) {
                    idleTimeoutFuture.cancel(true);
                    idleTimeoutFuture = null;
                }
            }
        } finally {
            SYNC_LOCK.unlock();
        }
    
<methods>public non-sealed void <init>() ,public T attr(java.lang.String) ,public void attr(java.lang.String, T) ,public boolean attrHas(java.lang.String) ,public Map<java.lang.String,java.lang.Object> attrMap() ,public T attrOrDefault(java.lang.String, T) ,public void close() ,public java.lang.String id() ,public boolean isClosed() ,public java.lang.String param(java.lang.String) ,public void param(java.lang.String, java.lang.String) ,public Map<java.lang.String,java.lang.String> paramMap() ,public java.lang.String paramOrDefault(java.lang.String, java.lang.String) ,public java.lang.String path() ,public void pathNew(java.lang.String) ,public java.lang.String url() <variables>private final Map<java.lang.String,java.lang.Object> attrMap,private org.noear.solon.net.websocket.Handshake handshake,private java.lang.String id,private boolean isClosed,static final org.slf4j.Logger log,private java.lang.String pathNew