zoukankan      html  css  js  c++  java
  • Apache common pool2 对象池

    对象池的容器:包含一个指定数量的对象。从池中取出一个对象时,它就不存在池中,直到它被放回。在池中的对象有生命周期:创建,验证,销毁,对象池有助于更好地管理可用资源,防止JVM内部大量临时小对象,频繁触发垃圾回收,造成系统暂停。有许多的使用示例。特别是在应用服务器数据源池,线程池等都是对象池的使用,下面情况适合使用对象池:

    • 同样的对象高频率使用
    • 对象太大消耗很多内存
    • 对象初始化需要时间
    • 对象内涉及IO操作 (Streams, Sockets, DB, etc.)
    • 对象并不是线程安全时。

    很多人使用 Apache Commons Pool.它有ObjectPool的接口,ObjectPoolFactory,PoolableObjectFactory和许多的实现。有addObject方法,borrowObject,invalidateObject,返回object添加,删除和返回对象。 PoolableObjectFactory定义对象池的操作行为,并提供各种回调。

    但是Apache Commons Pool不是一个轻量开销的对象池,它很多方法采用了不建议使用的旧的Java的关键字synchronized。而Java 5中引入了Executor框架Java并发(多线程)。这里是最好的Executor框架。

    package easypool;
    
    import java.util.concurrent.ConcurrentLinkedQueue;
    import java.util.concurrent.Executors;
    import java.util.concurrent.ScheduledExecutorService;
    import java.util.concurrent.TimeUnit;
    
    public abstract class ObjectPool<T>
    {
        private ConcurrentLinkedQueue<T> pool;
    
        private ScheduledExecutorService executorService;
    
        /**
         * Creates the pool.
         *
         * @param minIdle minimum number of objects residing in the pool
         */
        public ObjectPool(final int minIdle) {
            // initialize pool
            initialize(minIdle);
        }
    
        /**
         * Creates the pool.
         *
         * @param minIdle            minimum number of objects residing in the pool
         * @param maxIdle            maximum number of objects residing in the pool
         * @param validationInterval time in seconds for periodical checking of minIdle / maxIdle conditions in a separate thread.
         *                           When the number of objects is less than minIdle, missing instances will be created.
         *                           When the number of objects is greater than maxIdle, too many instances will be removed.
         */
        public ObjectPool(final int minIdle, final int maxIdle, final long validationInterval) {
            // initialize pool
            initialize(minIdle);
    
            // check pool conditions in a separate thread
            executorService = Executors.newSingleThreadScheduledExecutor();
            executorService.scheduleWithFixedDelay(new Runnable()
            {
                @Override
                public void run() {
                    int size = pool.size();
                    if (size < minIdle) {
                        int sizeToBeAdded = minIdle - size;
                        for (int i = 0; i < sizeToBeAdded; i++) {
                            pool.add(createObject());
                        }
                    } else if (size > maxIdle) {
                        int sizeToBeRemoved = size - maxIdle;
                        for (int i = 0; i < sizeToBeRemoved; i++) {
                            pool.poll();
                        }
                    }
                }
            }, validationInterval, validationInterval, TimeUnit.SECONDS);
        }
    
        /**
         * Gets the next free object from the pool. If the pool doesn't contain any objects,
         * a new object will be created and given to the caller of this method back.
         *
         * @return T borrowed object
         */
        public T borrowObject() {
            T object;
            if ((object = pool.poll()) == null) {
                object = createObject();
            }
    
            return object;
        }
    
        /**
         * Returns object back to the pool.
         *
         * @param object object to be returned
         */
        public void returnObject(T object) {
            if (object == null) {
                return;
            }
    
            this.pool.offer(object);
        }
    
        /**
         * Shutdown this pool.
         */
        public void shutdown() {
            if (executorService != null) {
                executorService.shutdown();
            }
        }
    
        /**
         * Creates a new object.
         *
         * @return T new object
         */
        protected abstract T createObject();
    
        private void initialize(final int minIdle) {
            pool = new ConcurrentLinkedQueue<T>();
    
            for (int i = 0; i < minIdle; i++) {
                pool.add(createObject());
            }
        }
    }
    package easypool;
    
    public class ExportingProcess {
    
        private String location;
    
        private long processNo = 0;
    
        public ExportingProcess(String location, long processNo) {
            this.location = location;
            this.processNo = processNo;
    
            // doing some time expensive calls / tasks
            // ...
    
            // for-loop is just for simulation
            for (int i = 0; i < Integer.MAX_VALUE; i++) {
            }
    
            System.out.println("Object with process no. " + processNo + " was created");
        }
    
        public String getLocation() {
            return location;
        }
    
        public long getProcessNo() {
            return processNo;
        }
    
        @Override
        public String toString() {
            return "ExportingProcess{" + "processNo=" + processNo + '}';
        }
    }
    package easypool;
    
    public class ExportingTask implements Runnable {
    
        private ObjectPool<ExportingProcess> pool;
    
        private int threadNo;
    
        public ExportingTask(ObjectPool<ExportingProcess> pool, int threadNo) {
            this.pool = pool;
            this.threadNo = threadNo;
        }
    
        public void run() {
            // get an object from the pool
            ExportingProcess exportingProcess = pool.borrowObject();
    
            System.out.println("Thread " + threadNo + 
                    ": Object with process no. " + exportingProcess.getProcessNo() + " was borrowed");
    
            // do something
            // ...
    
            // for-loop is just for simulation
            for (int i = 0; i < 100000; i++) {
            }
    
            // return ExportingProcess instance back to the pool
            pool.returnObject(exportingProcess);
    
            System.out.println("Thread " + threadNo + 
                    ": Object with process no. " + exportingProcess.getProcessNo() + " was returned");
        }
    }
    package easypool;
    
    import org.junit.After;
    import org.junit.Before;
    import org.junit.Test;
    
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.TimeUnit;
    import java.util.concurrent.atomic.AtomicLong;
    
    public class TestObjectPool
    {
        private ObjectPool<ExportingProcess> pool;
    
        private AtomicLong processNo = new AtomicLong(0);
    
        @Before
        public void setUp() {
            // Create a pool of objects of type ExportingProcess. Parameters:
            // 1) Minimum number of special ExportingProcess instances residing in the pool = 4
            // 2) Maximum number of special ExportingProcess instances residing in the pool = 10
            // 3) Time in seconds for periodical checking of minIdle / maxIdle conditions in a separate thread = 5.
            //    When the number of ExportingProcess instances is less than minIdle, missing instances will be created.
            //    When the number of ExportingProcess instances is greater than maxIdle, too many instances will be removed.
            //    If the validation interval is negative, no periodical checking of minIdle / maxIdle conditions
            //    in a separate thread take place. These boundaries are ignored then.
            pool = new ObjectPool<ExportingProcess>(4, 10, 5)
            {
                protected ExportingProcess createObject() {
                    // create a test object which takes some time for creation
                    return new ExportingProcess("/home/temp/", processNo.incrementAndGet());
                }
            };
        }
    
        @After
        public void tearDown() {
            pool.shutdown();
        }
    
        @Test
        public void testObjectPool() {
            ExecutorService executor = Executors.newFixedThreadPool(8);
    
            // execute 8 tasks in separate threads
            executor.execute(new ExportingTask(pool, 1));
            executor.execute(new ExportingTask(pool, 2));
            executor.execute(new ExportingTask(pool, 3));
            executor.execute(new ExportingTask(pool, 4));
            executor.execute(new ExportingTask(pool, 5));
            executor.execute(new ExportingTask(pool, 6));
            executor.execute(new ExportingTask(pool, 7));
            executor.execute(new ExportingTask(pool, 8));
    
            executor.shutdown();
            try {
                executor.awaitTermination(30, TimeUnit.SECONDS);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    测试》》》》》》》》》》》》》》》》》》》》》

    package test;
    public class StringFormat {
        public String format(String str)
        {
            return "formated:"+str;
        }
    }
    package test;
    import org.apache.commons.pool2.BasePooledObjectFactory;
    import org.apache.commons.pool2.PooledObject;
    import org.apache.commons.pool2.impl.DefaultPooledObject;
    
    public class StringFormatFactory
        extends BasePooledObjectFactory<StringFormat> {
    
        @Override
        public StringFormat create() {
            System.out.println("create object");
            return new StringFormat();
        }
    
        /**
         * Use the default PooledObject implementation.
         */
        @Override
        public PooledObject<StringFormat> wrap(StringFormat buffer) {
            return new DefaultPooledObject<StringFormat>(buffer);
        }
    
        /**
         * When an object is returned to the pool, clear the buffer.
         */
        @Override
        public void passivateObject(PooledObject<StringFormat> pooledObject) {
            System.out.println("Object been returned to pool");
        }
    
        // for all other methods, the no-op implementation
        // in BasePooledObjectFactory will suffice
    }
    package test;
    import java.io.IOException;
    import java.io.Reader;
    import java.util.ArrayList;
    import java.util.List;
    
    import org.apache.commons.pool2.ObjectPool;
    import org.apache.commons.pool2.impl.GenericObjectPool;
    import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
    
    public class StringProcessor {
    
        private ObjectPool<StringFormat> pool;
    
        public StringProcessor(ObjectPool<StringFormat> pool) {
            this.pool = pool;
        }
    
        /**
         * Dumps the contents of the {@link Reader} to a String, closing the
         * {@link Reader} when done.
         */
        public void process(List<String> strList) {
            for (String str : strList) {
                Thread thread = new StringProcessThread(pool, str);
                thread.start();
            }
            
            //设置等待两秒,等待线程结束
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    
        public static void main(String[] args) throws IOException {
            
            GenericObjectPoolConfig conf = new GenericObjectPoolConfig();
            conf.setMaxTotal(3);
            conf.setMaxIdle(2);
            conf.setMinIdle(2);
            
            
            StringProcessor stringProcessor = new StringProcessor(
                    new GenericObjectPool<StringFormat>(new StringFormatFactory(),conf));
            List<String> strList = new ArrayList<String>();
            strList.add("123");
            strList.add("456");
            strList.add("789");
            strList.add("111");
            strList.add("222");
            strList.add("333");
            stringProcessor.process(strList);
        }
    }
    package test;
    import org.apache.commons.pool2.ObjectPool;
    
    public class StringProcessThread extends Thread {
        private ObjectPool<StringFormat> pool;
        private String toProcessStr;
    
        public StringProcessThread(ObjectPool<StringFormat> pool,
                String toProcessStr) {
            this.pool = pool;
            this.toProcessStr = toProcessStr;
        }
    
        public void run() {
            StringFormat stringFormat = null;
            try {
                stringFormat = pool.borrowObject();
                String formattedStr = stringFormat.format(toProcessStr);
                System.out.println(formattedStr);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                try {
                    if (stringFormat != null) {
                        pool.returnObject(stringFormat);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    
    }
  • 相关阅读:
    淘宝首页广告圆角切换标签未解之谜(vml)
    chrome的google官方在线安装太坑爹了,找到一个离线下载地址
    kejun写的响应性设计和开发
    HTTP状态码
    xwebkitspeech 语音输入功能
    Avoid Redirects 避免重定向
    webstorm下使用github
    开通了github,用webstorm上传,敲命令行太累。
    jQuery1.6.1下event鼠标事件有BUG,升级到1.7.1可以解决问题。
    从程序员到项目经理(五):不是人人都懂的学习要点
  • 原文地址:https://www.cnblogs.com/jinzhiming/p/5120578.html
Copyright © 2011-2022 走看看