001 /**
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements. See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership. The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License. You may obtain a copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018
019 package org.apache.hadoop.util;
020
021 import com.google.common.annotations.VisibleForTesting;
022 import org.apache.commons.logging.Log;
023 import org.apache.commons.logging.LogFactory;
024
025 import java.util.concurrent.ExecutorService;
026 import java.util.concurrent.TimeUnit;
027
028 /**
029 * Helper class to shutdown {@link Thread}s and {@link ExecutorService}s.
030 */
031 public class ShutdownThreadsHelper {
032 private static Log LOG = LogFactory.getLog(ShutdownThreadsHelper.class);
033
034 @VisibleForTesting
035 static final int SHUTDOWN_WAIT_MS = 3000;
036
037 /**
038 * @param thread {@link Thread to be shutdown}
039 * @return <tt>true</tt> if the thread is successfully interrupted,
040 * <tt>false</tt> otherwise
041 * @throws InterruptedException
042 */
043 public static boolean shutdownThread(Thread thread) {
044 return shutdownThread(thread, SHUTDOWN_WAIT_MS);
045 }
046
047 /**
048 * @param thread {@link Thread to be shutdown}
049 * @param timeoutInMilliSeconds time to wait for thread to join after being
050 * interrupted
051 * @return <tt>true</tt> if the thread is successfully interrupted,
052 * <tt>false</tt> otherwise
053 * @throws InterruptedException
054 */
055 public static boolean shutdownThread(Thread thread,
056 long timeoutInMilliSeconds) {
057 if (thread == null) {
058 return true;
059 }
060
061 try {
062 thread.interrupt();
063 thread.join(timeoutInMilliSeconds);
064 return true;
065 } catch (InterruptedException ie) {
066 LOG.warn("Interrupted while shutting down thread - " + thread.getName());
067 return false;
068 }
069 }
070
071 /**
072 * @param service {@link ExecutorService to be shutdown}
073 * @return <tt>true</tt> if the service is terminated,
074 * <tt>false</tt> otherwise
075 * @throws InterruptedException
076 */
077 public static boolean shutdownExecutorService(ExecutorService service)
078 throws InterruptedException {
079 return shutdownExecutorService(service, SHUTDOWN_WAIT_MS);
080 }
081
082 /**
083 * @param service {@link ExecutorService to be shutdown}
084 * @param timeoutInMs time to wait for {@link
085 * ExecutorService#awaitTermination(long, java.util.concurrent.TimeUnit)}
086 * calls in milli seconds.
087 * @return <tt>true</tt> if the service is terminated,
088 * <tt>false</tt> otherwise
089 * @throws InterruptedException
090 */
091 public static boolean shutdownExecutorService(ExecutorService service,
092 long timeoutInMs)
093 throws InterruptedException {
094 if (service == null) {
095 return true;
096 }
097
098 service.shutdown();
099 if (!service.awaitTermination(timeoutInMs, TimeUnit.MILLISECONDS)) {
100 service.shutdownNow();
101 return service.awaitTermination(timeoutInMs, TimeUnit.MILLISECONDS);
102 } else {
103 return true;
104 }
105 }
106 }