/* * (C) Copyright 2015-2016 the original author or authors. * * 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. * * Contributors: * ohun@live.cn (夜色) */ package com.mpush.tools.thread.pool; import com.mpush.api.push.PushException; import com.mpush.api.spi.Spi; import com.mpush.api.spi.common.ExecutorFactory; import com.mpush.tools.config.CC; import com.mpush.tools.log.Logs; import com.mpush.tools.thread.NamedPoolThreadFactory; import java.util.concurrent.*; import static com.mpush.tools.config.CC.mp.thread.pool.ack_timer; import static com.mpush.tools.config.CC.mp.thread.pool.push_client; import static com.mpush.tools.config.CC.mp.thread.pool.push_task; import static com.mpush.tools.thread.ThreadNames.*; /** * 此线程池可伸缩,线程空闲一定时间后回收,新请求重新创建线程 */ @Spi(order = 1) public final class DefaultExecutorFactory implements ExecutorFactory { private Executor get(ThreadPoolConfig config) { String name = config.getName(); int corePoolSize = config.getCorePoolSize(); int maxPoolSize = config.getMaxPoolSize(); int keepAliveSeconds = config.getKeepAliveSeconds(); BlockingQueue<Runnable> queue = config.getQueue(); return new DefaultExecutor(corePoolSize , maxPoolSize , keepAliveSeconds , TimeUnit.SECONDS , queue , new NamedPoolThreadFactory(name) , new DumpThreadRejectedHandler(config)); } @Override public Executor get(String name) { final ThreadPoolConfig config; switch (name) { case EVENT_BUS: config = ThreadPoolConfig .build(T_EVENT_BUS) .setCorePoolSize(CC.mp.thread.pool.event_bus.min) .setMaxPoolSize(CC.mp.thread.pool.event_bus.max) .setKeepAliveSeconds(TimeUnit.SECONDS.toSeconds(10)) .setQueueCapacity(CC.mp.thread.pool.event_bus.queue_size) .setRejectedPolicy(ThreadPoolConfig.REJECTED_POLICY_CALLER_RUNS); break; case MQ: config = ThreadPoolConfig .build(T_MQ) .setCorePoolSize(CC.mp.thread.pool.mq.min) .setMaxPoolSize(CC.mp.thread.pool.mq.max) .setKeepAliveSeconds(TimeUnit.SECONDS.toSeconds(10)) .setQueueCapacity(CC.mp.thread.pool.mq.queue_size) .setRejectedPolicy(ThreadPoolConfig.REJECTED_POLICY_CALLER_RUNS); ; break; case PUSH_CLIENT: { ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(push_client , new NamedPoolThreadFactory(T_PUSH_CLIENT_TIMER), (r, e) -> r.run() // run caller thread ); executor.setRemoveOnCancelPolicy(true); return executor; } case PUSH_TASK: return new ScheduledThreadPoolExecutor(push_task, new NamedPoolThreadFactory(T_PUSH_CENTER_TIMER), (r, e) -> { throw new PushException("one push task was rejected. task=" + r); } ); case ACK_TIMER: { ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(ack_timer, new NamedPoolThreadFactory(T_ARK_REQ_TIMER), (r, e) -> Logs.PUSH.error("one ack context was rejected, context=" + r) ); executor.setRemoveOnCancelPolicy(true); return executor; } default: throw new IllegalArgumentException("no executor for " + name); } return get(config); } }