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

com.github.javaclub.toolbox.thread.memlimit.MemorySafeLinkedBlockingQueue Maven / Gradle / Ivy

There is a newer version: 2.7.44
Show newest version
/*
 * @(#)MemorySafeLinkedBlockingQueue.java	2022-6-16
 *
 * Copyright (c) 2022. All Rights Reserved.
 *
 */

package com.github.javaclub.toolbox.thread.memlimit;

import java.util.Collection;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.github.javaclub.Constants.MemCapacity;

/**
 * Can completely solve the OOM problem caused by {@link java.util.concurrent.LinkedBlockingQueue},
 * does not depend on {@link java.lang.instrument.Instrumentation} and is easier to use than
 * {@link LinkedBlockingQueue} with Memory Safely policy.
 *
 * @see MemorySafeLinkedBlockingQueue
 */
public class MemorySafeLinkedBlockingQueue extends LinkedBlockingQueue {

    private static final long serialVersionUID = 8032578371739960142L;
    
    private static final Logger log = LoggerFactory.getLogger(MemorySafeLinkedBlockingQueue.class);

    /**
     * JVM可用内存大小默认保留值(16MB)
     */
    private static final int JVM_RESERVED_MEM_DEFAULT = MemCapacity.intBytesOfMB(16);

    /**
     * 为JVM预设保留的空闲内存,当JVM剩余可用内存小于此值时,不允许往队列提交新Element
     */
    private int maxFreeMemory;

    public MemorySafeLinkedBlockingQueue() {
        this(Integer.MAX_VALUE, JVM_RESERVED_MEM_DEFAULT);
    }
    
    public MemorySafeLinkedBlockingQueue(final int queueCapacity) {
        this(queueCapacity, JVM_RESERVED_MEM_DEFAULT);
    }

    /**
     * @param maxFreeMemory 为JVM兜底保留的空闲内存大小字节数(防止OOM)
     */
    public MemorySafeLinkedBlockingQueue(final int queueCapacity, final int maxFreeMemory) {
        super(queueCapacity);
        this.maxFreeMemory = maxFreeMemory;
    }

    public MemorySafeLinkedBlockingQueue(final Collection c,
                                         final int maxFreeMemory) {
        super(c);
        this.maxFreeMemory = maxFreeMemory;
    }

    /**
     * set the max free memory.
     *
     * @param maxFreeMemory the max free memory
     */
    public void setMaxFreeMemory(final int maxFreeMemory) {
        this.maxFreeMemory = maxFreeMemory;
    }

    /**
     * get the max free memory.
     *
     * @return the max free memory limit
     */
    public int getMaxFreeMemory() {
        return maxFreeMemory;
    }

    /**
     * determine if there is any remaining free memory.
     *
     * @return true if has free memory
     */
    public boolean hasRemainedMemory() {
        return MemoryLimitCalculator.maxAvailable() > maxFreeMemory;
    }

    @Override
    public void put(final E e) throws InterruptedException {
        if (hasRemainedMemory()) {
            super.put(e);
            return;
        }
        log.warn("BlockingQueue can't accept more by memory limited.");
    }

    @Override
    public boolean offer(final E e, final long timeout, final TimeUnit unit) throws InterruptedException {
    	if (hasRemainedMemory()) {
    		return super.offer(e, timeout, unit);
    	}
    	log.warn("BlockingQueue can't handle more by memory limited.");
        return false;
    }

    @Override
    public boolean offer(final E e) {
    	if (hasRemainedMemory()) {
    		return super.offer(e);
    	}
    	log.warn("BlockingQueue can't handle more by memory limited.");
        return false;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy