Java tutorial
/* * This file is part of Cherry. * * Cherry is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Cherry is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with Cherry. If not, see <http://www.gnu.org/licenses/>. * */ package net.sheehantech.cherry.pool; import net.sheehantech.cherry.*; import org.apache.commons.pool2.impl.GenericObjectPool; import org.apache.commons.pool2.impl.GenericObjectPoolConfig; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.net.ssl.SSLContext; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; public class PooledPushClient extends AbstractAsyncPushClient { private Logger logger = LoggerFactory.getLogger(PooledPushClient.class); private GenericObjectPool<PooledPushSocket> pool; private Integer maxTotal; private Integer minIdle; private Integer maxIdle; private ExecutorService executor; public PooledPushClient(SSLContext sslContext) { super(sslContext); executor = Executors.newCachedThreadPool(); } public Integer getMaxTotal() { return maxTotal; } public void setMaxTotal(Integer maxTotal) { this.maxTotal = maxTotal; } public Integer getMaxIdle() { return maxIdle; } public void setMaxIdle(Integer maxIdle) { this.maxIdle = maxIdle; } public Integer getMinIdle() { return minIdle; } public void setMinIdle(Integer minIdle) { this.minIdle = minIdle; } @Override public void init() throws ConnectionFailedException { GenericObjectPoolConfig config = new GenericObjectPoolConfig(); if (maxTotal != null) config.setMaxTotal(maxTotal); if (maxIdle != null) config.setMaxIdle(maxIdle); if (minIdle != null) config.setMinIdle(minIdle); config.setTestOnBorrow(true); config.setTestWhileIdle(true); config.setBlockWhenExhausted(true); pool = new GenericObjectPool<PooledPushSocket>(new PooledPushSocketFactory(socketFactory, gateway, port), config); try { pool.preparePool(); } catch (Exception e) { throw (new ConnectionFailedException(e)); } logger.debug("Started new push socket pool with {} sockets", pool.getNumIdle()); } @Override public void shutdown() { while (!pool.isClosed()) { if (pool.getNumActive() == 0) { pool.close(); logger.info("Shut down pool"); } else { try { logger.debug("Waiting for {} active sockets", pool.getNumActive()); Thread.sleep(100); } catch (InterruptedException e) { logger.debug("Interrrupted during graceful shutdown"); } } } } @Override public void shutdownNow() { pool.close(); } @Override public Future<PushResult> send(Notification notification) throws PushFailedException { try { notification.setId(nextId()); Future<PushResult> pushResultFuture = executor .submit(new PooledSendNotificationTask(pool, notification)); logger.debug("Sent notification {}", notification.getId()); return pushResultFuture; } catch (Exception e) { throw (new PushFailedException(e)); } } }