All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.jahhan.extension.threadPool.AbortPolicyWithReport Maven / Gradle / Ivy

/*
 * Copyright 1999-2011 Alibaba Group.
 *  
 * 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 net.jahhan.extension.threadPool;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.Executors;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.Semaphore;
import java.util.concurrent.ThreadPoolExecutor;

import com.alibaba.dubbo.common.Constants;
import com.alibaba.dubbo.common.URL;
import com.alibaba.dubbo.common.utils.JVMUtil;

import lombok.extern.slf4j.Slf4j;

/**
 * Abort Policy. Log warn info when abort.
 * 
 * @author ding.lid
 */
@Slf4j
public class AbortPolicyWithReport extends ThreadPoolExecutor.AbortPolicy {

	private final String threadName;

	private final URL url;

	private static volatile long lastPrintTime = 0;

	private static Semaphore guard = new Semaphore(1);

	public AbortPolicyWithReport(String threadName, URL url) {
		this.threadName = threadName;
		this.url = url;
	}

	@Override
	public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
		String msg = String.format(
				"Thread pool is EXHAUSTED!"
						+ " Thread Name: %s, Pool Size: %d (active: %d, core: %d, max: %d, largest: %d), Task: %d (completed: %d),"
						+ " Executor status:(isShutdown:%s, isTerminated:%s, isTerminating:%s), in %s://%s:%d!",
				threadName, e.getPoolSize(), e.getActiveCount(), e.getCorePoolSize(), e.getMaximumPoolSize(),
				e.getLargestPoolSize(), e.getTaskCount(), e.getCompletedTaskCount(), e.isShutdown(), e.isTerminated(),
				e.isTerminating(), url.getProtocol(), url.getIp(), url.getPort());
		log.warn(msg);
		dumpJStack();
		throw new RejectedExecutionException(msg);
	}

	private void dumpJStack() {
		long now = System.currentTimeMillis();

		// 十分钟打一次
		if (now - lastPrintTime < 10 * 60 * 1000) {
			return;
		}

		if (!guard.tryAcquire()) {
			return;
		}

		Executors.newSingleThreadExecutor().execute(new Runnable() {
			@Override
			public void run() {
				String dumpPath = url.getParameter(Constants.DUMP_DIRECTORY, System.getProperty("user.home"));
				SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd_HH:mm:ss");
				String dateStr = sdf.format(new Date());
				FileOutputStream jstackStream = null;
				try {
					jstackStream = new FileOutputStream(new File(dumpPath, "Dubbo_JStack.log" + "." + dateStr));
					JVMUtil.jstack(jstackStream);
				} catch (Throwable t) {
					log.error("dump jstack error", t);
				} finally {
					guard.release();
					if (jstackStream != null) {
						try {
							jstackStream.flush();
							jstackStream.close();
						} catch (IOException e) {
						}
					}
				}

				lastPrintTime = System.currentTimeMillis();
			}
		});

	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy