/* * Copyright 2016-2018 Nextop Co.,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 cn.nextop.lite.pool.util.concurrent.executor; import cn.nextop.lite.pool.util.Strings; import cn.nextop.lite.pool.util.concurrent.thread.XThreadFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.List; import java.util.concurrent.BlockingQueue; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.RejectedExecutionHandler; import java.util.concurrent.RunnableFuture; import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; /** * @author Jingqi Xu */ public class XThreadPoolExecutor extends ThreadPoolExecutor implements XExecutorService { // private static final Logger LOGGER = LoggerFactory.getLogger(XThreadPoolExecutor.class); // private final String name; private boolean verbose = true; private final CopyOnWriteArrayList<Listener> listeners = new CopyOnWriteArrayList<Listener>(); /** * */ public XThreadPoolExecutor(String name, int size, int max) { this(name, size, max, new LinkedBlockingQueue<Runnable>()); } public XThreadPoolExecutor(String name, int size, int max, ThreadFactory factory) { this(name, size, max, new LinkedBlockingQueue<Runnable>(), factory); } public XThreadPoolExecutor(String name, int size, int max, BlockingQueue<Runnable> queue) { this(name, size, max, queue, new XThreadFactory(name)); } public XThreadPoolExecutor(String name, int size, int max, BlockingQueue<Runnable> queue, ThreadFactory factory) { this(name, size, max, 0L, TimeUnit.MILLISECONDS, queue, factory, new AbortPolicy()); } public XThreadPoolExecutor(String name, int size, int max, long alive, TimeUnit unit, BlockingQueue<Runnable> queue, ThreadFactory factory) { this(name, size, max, alive, unit, queue, factory, new AbortPolicy()); } public XThreadPoolExecutor(String name, int size, int max, long alive, TimeUnit unit, BlockingQueue<Runnable> queue, ThreadFactory factory, RejectedExecutionHandler handler) { super(size, max, alive, unit, queue, factory, handler); this.name = name; } /** * */ @Override public String toString() { return Strings.build(this) .append("name", name) .append("verbose", verbose).toString(); } /** * */ @Override public void execute(Runnable command) { // RunnableFuture<?> rf = null; if(command instanceof RunnableFuture) { // Called by submit() rf = (RunnableFuture<?>)command; } else { rf = newTaskFor(command, null); } // try { notifyPrevEnqueue(rf); } finally { super.execute(rf); } } /** * */ @Override public String getName() { return name; } @Override public boolean isVerbose() { return verbose; } @Override public void setVerbose(boolean verbose) { this.verbose = verbose; } @Override public List<Listener> getListeners() { return this.listeners; } @Override public boolean addListener(Listener listener) { return this.listeners.add(listener); } @Override public boolean delListener(Listener listener) { return this.listeners.remove(listener); } @Override public void setListeners(List<Listener> listeners) { this.listeners.clear(); if(listeners != null) this.listeners.addAll(listeners); } /** * */ @Override protected void terminated() { super.terminated(); notifyOnTerminated(); } @Override protected void beforeExecute(Thread t, Runnable runnable) { // super.beforeExecute(t, runnable); this.notifyPrevExecute((RunnableFuture<?>)runnable); } @Override protected void afterExecute(Runnable runnable, Throwable t) { // super.afterExecute(runnable, t); this.notifyPostExecute((RunnableFuture<?>)runnable, t); } /** * */ protected final void notifyOnTerminated() { if(this.listeners.size() == 0) return; for(final Listener listener : this.listeners) { try { listener.onTerminated(this); } catch(Throwable tx) { LOGGER.error("["+ getName() + "]failed to notify onTerminated, listener: " + listener, tx); } } } protected final void notifyPrevEnqueue(RunnableFuture<?> future) { if(this.listeners.size() == 0) return; for(final Listener listener : this.listeners) { try { listener.prevEnqueue(this, future); } catch(Throwable e) { LOGGER.error("["+ this.getName() + "]failed to notify prevEnqueue, listener: " + listener, e); } } } protected final void notifyPrevExecute(RunnableFuture<?> future) { if(this.listeners.size() == 0) return; for(final Listener listener : this.listeners) { try { listener.prevExecute(this, future); } catch(Throwable tx) { LOGGER.error("["+ this.getName() + "]failed to notify prevExecute, listener: " + listener, tx); } } } protected final void notifyPostExecute(RunnableFuture<?> future, Throwable t) { if(this.listeners.size() == 0) return; for(final Listener listener : this.listeners) { try { listener.postExecute(this, future, t); } catch(Throwable tx) { LOGGER.error("["+ this.getName() + "]failed to notify postExecute, listener: " + listener, tx); } } } }