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

com.alipay.sofa.common.thread.SofaScheduledThreadPoolExecutor Maven / Gradle / Ivy

The newest version!
/*
 * 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.
 */
package com.alipay.sofa.common.thread;

import com.alipay.sofa.common.thread.log.ThreadLogger;
import com.alipay.sofa.common.thread.space.SpaceNamedThreadFactory;
import com.alipay.sofa.common.utils.StringUtil;

import java.util.concurrent.Callable;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * Sofa thread pool based on {@link ScheduledThreadPoolExecutor}
 * @author huzijie
 * @version SofaScheduledThreadPoolExecutor.java, v 0.1 2020年11月09日 2:19 下午 huzijie Exp $
 */
public class SofaScheduledThreadPoolExecutor extends ScheduledThreadPoolExecutor {
    private static final String        SIMPLE_CLASS_NAME  = SofaScheduledThreadPoolExecutor.class
                                                              .getSimpleName();
    private static final AtomicInteger POOL_COUNTER       = new AtomicInteger(0);
    private final ThreadPoolConfig     config;
    private final ThreadPoolStatistics statistics;
    private boolean                    sofaTracerTransmit = false;

    /**
     * Basic constructor
     * @param corePoolSize same as in {@link ScheduledThreadPoolExecutor}
     * @param threadFactory same as in {@link ScheduledThreadPoolExecutor}
     * @param handler same as in {@link ScheduledThreadPoolExecutor}
     * @param threadPoolName name of this thread pool
     * @param spaceName spaceName of this tread pool
     * @param taskTimeout task execution timeout
     * @param period task checking and logging period
     * @param timeUnit unit of taskTimeout and period
     */
    public SofaScheduledThreadPoolExecutor(int corePoolSize, ThreadFactory threadFactory,
                                           RejectedExecutionHandler handler, String threadPoolName,
                                           String spaceName, long taskTimeout, long period,
                                           TimeUnit timeUnit) {
        super(corePoolSize, threadFactory, handler);
        this.config = ThreadPoolConfig.newBuilder()
            .threadPoolName(StringUtil.isEmpty(threadPoolName) ? createName() : threadPoolName)
            .spaceName(spaceName).taskTimeout(taskTimeout).period(period).timeUnit(timeUnit)
            .build();
        this.statistics = new ThreadPoolStatistics(this);
        ThreadPoolGovernor.getInstance().registerThreadPoolExecutor(this, config, statistics);
    }

    public SofaScheduledThreadPoolExecutor(int corePoolSize, ThreadFactory threadFactory,
                                           RejectedExecutionHandler handler, String threadPoolName,
                                           long taskTimeout, long period, TimeUnit timeUnit) {
        this(corePoolSize, threadFactory, handler, threadPoolName, null, taskTimeout, period,
            timeUnit);
    }

    public SofaScheduledThreadPoolExecutor(int corePoolSize, ThreadFactory threadFactory,
                                           RejectedExecutionHandler handler, String threadPoolName,
                                           String spaceName) {
        this(corePoolSize, threadFactory, handler, threadPoolName, spaceName, 0, 0, null);
    }

    public SofaScheduledThreadPoolExecutor(int corePoolSize, ThreadFactory threadFactory,
                                           RejectedExecutionHandler handler, String threadPoolName) {
        this(corePoolSize, threadFactory, handler, threadPoolName, 0, 0, null);
    }

    public SofaScheduledThreadPoolExecutor(int corePoolSize, String threadPoolName, String spaceName) {
        super(corePoolSize);
        this.config = ThreadPoolConfig.newBuilder()
            .threadPoolName(StringUtil.isEmpty(threadPoolName) ? createName() : threadPoolName)
            .spaceName(spaceName).build();
        this.statistics = new ThreadPoolStatistics(this);
        ThreadPoolGovernor.getInstance().registerThreadPoolExecutor(this, config, statistics);
        if (StringUtil.isNotEmpty(threadPoolName)) {
            if (StringUtil.isNotEmpty(spaceName)) {
                this.setThreadFactory(new SpaceNamedThreadFactory(threadPoolName, spaceName));
            } else {
                this.setThreadFactory(new NamedThreadFactory(threadPoolName));
            }
        }
    }

    public SofaScheduledThreadPoolExecutor(int corePoolSize, String threadPoolName) {
        this(corePoolSize, threadPoolName, null);
    }

    public SofaScheduledThreadPoolExecutor(int corePoolSize) {
        this(corePoolSize, "", null);
    }

    public SofaScheduledThreadPoolExecutor(int corePoolSize, ThreadFactory threadFactory) {
        this(corePoolSize);
        this.setThreadFactory(threadFactory);
    }

    public SofaScheduledThreadPoolExecutor(int corePoolSize, RejectedExecutionHandler handler) {
        this(corePoolSize);
        this.setRejectedExecutionHandler(handler);
    }

    public SofaScheduledThreadPoolExecutor(int corePoolSize, ThreadFactory threadFactory,
                                           RejectedExecutionHandler handler) {
        this(corePoolSize);
        this.setThreadFactory(threadFactory);
        this.setRejectedExecutionHandler(handler);
    }

    private String createName() {
        return SIMPLE_CLASS_NAME + String.format("%08x", POOL_COUNTER.getAndIncrement());
    }

    @Override
    protected void beforeExecute(Thread t, Runnable r) {
        super.beforeExecute(t, r);
        ExecutingRunnable runner = new ExecutingRunnable(r);
        runner.setThread(t);
        this.statistics.getExecutingTasks().put(runner, System.currentTimeMillis());
    }

    @Override
    protected void afterExecute(Runnable r, Throwable t) {
        super.afterExecute(r, t);
        ExecutingRunnable runner = new ExecutingRunnable(r);
        runner.setThread(Thread.currentThread());
        this.statistics.addTotalRunningTime(System.currentTimeMillis()
                                            - statistics.getExecutingTasks().get(runner));
        this.statistics.addTotalTaskCount();
        this.statistics.getExecutingTasks().remove(runner);
    }

    @Override
    protected void terminated() {
        super.terminated();
        ThreadPoolGovernor.getInstance().unregisterThreadPoolExecutor(this.getConfig());
    }

    public synchronized void startSchedule() {
        ThreadPoolGovernor.getInstance().startMonitorThreadPool(config.getIdentity());
    }

    public synchronized void stopSchedule() {
        ThreadPoolGovernor.getInstance().stopMonitorThreadPool(config.getIdentity());
    }

    public synchronized void reschedule() {
        ThreadPoolGovernor.getInstance().restartMonitorThreadPool(config.getIdentity());
    }

    public void updateThreadPoolName(String threadPoolName) {
        ThreadPoolGovernor.getInstance().unregisterThreadPoolExecutor(this.getConfig());
        this.config.setThreadPoolName(threadPoolName);
        ThreadPoolGovernor.getInstance().registerThreadPoolExecutor(this, config, statistics);
    }

    public void updatespaceName(String spaceName) {
        ThreadPoolGovernor.getInstance().unregisterThreadPoolExecutor(this.getConfig());
        this.config.setSpaceName(spaceName);
        ThreadPoolGovernor.getInstance().registerThreadPoolExecutor(this, config, statistics);
    }

    public void updatePeriod(long period) {
        this.config.setPeriod(period);
        reschedule();
    }

    public void updateTaskTimeout(long taskTimeout) {
        this.config.setTaskTimeout(taskTimeout);
        this.config.setTaskTimeoutMilli(this.config.getTimeUnit().toMillis(taskTimeout));
        ThreadLogger.info("Updated '{}' taskTimeout to {} {}", this.config.getIdentity(),
            taskTimeout, this.config.getTimeUnit());
    }

    public ThreadPoolConfig getConfig() {
        return config;
    }

    public ThreadPoolStatistics getStatistics() {
        return statistics;
    }

    public ScheduledFuture schedule(Runnable command, long delay, TimeUnit unit) {
        if (sofaTracerTransmit) {
            command = SofaTracerCommandFactory.ofRunnable(command);
        }
        return super.schedule(command, delay, unit);
    }

    public  ScheduledFuture schedule(Callable callable, long delay, TimeUnit unit) {
        if (sofaTracerTransmit) {
            callable = SofaTracerCommandFactory.ofCallable(callable);
        }
        return super.schedule(callable, delay, unit);
    }

    public ScheduledFuture scheduleAtFixedRate(Runnable command, long initialDelay, long period,
                                                  TimeUnit unit) {
        if (sofaTracerTransmit) {
            command = SofaTracerCommandFactory.ofRunnable(command);
        }
        return super.scheduleAtFixedRate(command, initialDelay, period, unit);
    }

    public ScheduledFuture scheduleWithFixedDelay(Runnable command, long initialDelay,
                                                     long delay, TimeUnit unit) {
        if (sofaTracerTransmit) {
            command = SofaTracerCommandFactory.ofRunnable(command);
        }
        return super.scheduleWithFixedDelay(command, initialDelay, delay, unit);
    }

    public void setSofaTracerTransmit(boolean sofaTracerTransmit) {
        this.sofaTracerTransmit = sofaTracerTransmit;
    }

    public boolean isSofaTracerTransmit() {
        return sofaTracerTransmit;
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy