📄 bytearraypool.java
字号:
// ========================================================================// $Id: ByteArrayPool.java,v 1.5 2004/12/01 21:00:24 hoschek3 Exp $// Copyright 2002-2004 Mort Bay Consulting Pty. Ltd.// ------------------------------------------------------------------------// Licensed under the Apache License, Version 2.0 (the "License");// you may not use this file except in compliance with the License.// You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0// Unless required by applicable law or agreed to in writing, software// distributed under the License is distributed on an "AS IS" BASIS,// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.// See the License for the specific language governing permissions and// limitations under the License.// ========================================================================package gov.lbl.dsd.sea.nio.util;/** * Simple fixed-size thread-safe pool for recycling byte arrays. Each thread has * its own local pool, and each pool can hold at most a given number of byte * arrays, evicting arrays beyond that point, as configured through a system * property. * <p> * Completely unsynchronized, yet thread-safe implementation. * <p> * Simple, but often effective if an application creates medium to large * temporary arrays at very high frequency, as is often the case in safe and * clean I/O buffer management for network servers. * <p> * This is not a general purpose replacement for Javas built-in memory and * garbage collection subsystem! Do not abuse this class for small or infrequent * arrays - those are handled better (read: near-optimal) by the generational * garbage collectors and memory allocators of current VMs. * * @version $Id: ByteArrayPool.java,v 1.5 2004/12/01 21:00:24 hoschek3 Exp $ * @author Greg Wilkins (gregw) * @author whoschek@lbl.gov (local improvements to apache-licensed jetty code) */public final class ByteArrayPool { private static final int MAX_POOL_ENTRIES = Integer.getInteger( ByteArrayPool.class.getName() + ".maxPoolEntries", 8).intValue(); private static final int MIN_ARRAY_SIZE = Integer.getInteger( ByteArrayPool.class.getName() + ".minArraySize", 512 + 1).intValue(); private static final int MAX_ARRAY_SIZE = Integer.getInteger( ByteArrayPool.class.getName() + ".maxArraySize", Integer.MAX_VALUE).intValue(); private static final ThreadLocal localPool = new ThreadLocalPool(); private static int slot; private static final boolean debug = false; // hotspot vm removes dead code if false private ByteArrayPool() {} // not instantiable /** * Returns a byte array that has exactly the given size. If there is no such * array in the pool, then creates and returns a new array with the given * size. * * @param size * the desired size of the byte array. * @return Byte array of desired size. */ public static byte[] takeExactly(int size) { if (size >= MIN_ARRAY_SIZE && size <= MAX_ARRAY_SIZE) { byte[][] pool = (byte[][]) localPool.get(); boolean full = true; for (int i = pool.length; i-- > 0;) { if (pool[i] != null && pool[i].length == size) { byte[] bytes = pool[i]; pool[i] = null; if (debug) memset(bytes, (byte) 0); return bytes; } else full = false; } if (full) for (int i = pool.length; i-- > 0;) pool[i] = null; } return new byte[size]; } /** * Returns a byte array that has at least the given size. If there is no * such array in the pool, then creates and returns a new array with the * given minSize. * * @param minSize * the minimum desired size of the byte array. * @return Byte array of desired size. */ public static byte[] take(int minSize) { if (minSize >= MIN_ARRAY_SIZE && minSize <= MAX_ARRAY_SIZE) { byte[][] pool = (byte[][]) localPool.get(); for (int i = pool.length; i-- > 0;) { if (pool[i] != null && pool[i].length >= minSize) { byte[] bytes = pool[i]; pool[i] = null; if (debug) memset(bytes, (byte) 0); return bytes; } } } return new byte[minSize]; } /** * Recycles the given byte array back to the pool. * * @param bytes the array to recycle */ public static void put(final byte[] bytes) { if (bytes == null || bytes.length < MIN_ARRAY_SIZE || bytes.length > MAX_ARRAY_SIZE) return; if (debug) memset(bytes, (byte) 0); final byte[][] pool = (byte[][]) localPool.get(); for (int i = pool.length; i-- > 0;) { if (pool[i] == null) { pool[i] = bytes; return; } } putEvict(bytes, pool); } private static void putEvict(final byte[] bytes, final byte[][] pool) { // int load is guaranteed to be atomic by VM spec. // plus, we handle races on store safely... int s = slot++; if (s < 0) s = -s; pool[s % pool.length] = bytes; } /** * Sets all elements of the given array to the given value. * * @param bytes the array to initialize */ private static void memset(final byte[] bytes, final byte value) { for (int i = bytes.length; --i >= 0; ) bytes[i] = value; } /* ------------------------------------------------------------ */ private static final class ThreadLocalPool extends ThreadLocal { protected Object initialValue() { return new byte[MAX_POOL_ENTRIES][]; } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -