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 019package org.apache.hadoop.util; 020 021import com.google.common.annotations.VisibleForTesting; 022import org.apache.commons.logging.Log; 023import org.apache.commons.logging.LogFactory; 024 025import java.util.concurrent.ExecutorService; 026import java.util.concurrent.TimeUnit; 027 028/** 029 * Helper class to shutdown {@link Thread}s and {@link ExecutorService}s. 030 */ 031public 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}