Java tutorial
//package com.java2s; /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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. */ import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.Collections; import java.util.concurrent.ExecutorService; import java.util.concurrent.atomic.AtomicBoolean; public class Main { /** * Wraps an {@link ExecutorService} in such a way as to "protect" * it for calls to the {@link ExecutorService#shutdown()} or * {@link ExecutorService#shutdownNow()}. All other calls are delegated as-is * to the original service. <B>Note:</B> the exposed wrapped proxy will * answer correctly the {@link ExecutorService#isShutdown()} query if indeed * one of the {@code shutdown} methods was invoked. * * @param executorService The original service - ignored if {@code null} * @param shutdownOnExit If {@code true} then it is OK to shutdown the executor * so no wrapping takes place. * @return Either the original service or a wrapped one - depending on the * value of the <tt>shutdownOnExit</tt> parameter */ public static ExecutorService protectExecutorServiceShutdown(final ExecutorService executorService, boolean shutdownOnExit) { if (executorService == null || shutdownOnExit) { return executorService; } else { return (ExecutorService) Proxy.newProxyInstance(resolveDefaultClassLoader(executorService), new Class<?>[] { ExecutorService.class }, new InvocationHandler() { private final AtomicBoolean stopped = new AtomicBoolean(false); @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { String name = method.getName(); if ("isShutdown".equals(name)) { return stopped.get(); } else if ("shutdown".equals(name)) { stopped.set(true); return null; // void... } else if ("shutdownNow".equals(name)) { stopped.set(true); return Collections.emptyList(); } else { return method.invoke(executorService, args); } } }); } } public static ClassLoader resolveDefaultClassLoader(Object anchor) { return resolveDefaultClassLoader(anchor == null ? null : anchor.getClass()); } /** * <P>Attempts to find the most suitable {@link ClassLoader} as follows:</P> * <UL> * <LI><P> * Check the {@link Thread#getContextClassLoader()} value * </P></LI> * * <LI><P> * If no thread context class loader then check the anchor * class (if given) for its class loader * </P></LI> * * <LI><P> * If still no loader available, then use {@link ClassLoader#getSystemClassLoader()} * </P></LI> * </UL> * * @param anchor The anchor {@link Class} to use if no current thread * - ignored if {@code null} * context class loader * @return The resolver {@link ClassLoader} */ public static ClassLoader resolveDefaultClassLoader(Class<?> anchor) { Thread thread = Thread.currentThread(); ClassLoader cl = thread.getContextClassLoader(); if (cl != null) { return cl; } if (anchor != null) { cl = anchor.getClassLoader(); } if (cl == null) { // can happen for core Java classes cl = ClassLoader.getSystemClassLoader(); } return cl; } }