The clever design of the thread pool of Nacos source code analysis (1) can be added to your own project

Hello everyone, let me introduce myself to you first.
I am the code on the code. You can call me brother code.
I am also the most ordinary student who graduated from an ordinary undergraduate course. I believe that most programmers or those who want to work in the programmer industry are ordinary families. My child, so I also rely on my own efforts, from graduating and joining a traditional company, to changing jobs without fail, and now working in a giant company in the Internet industry, I hope that through my sharing, I can help everyone.
Follow my column to learn , which can save you a lot of training costs or time to find information online, save most of your time costs, and make you faster to become an interview harvester and the best employee of the year

I have prepared 16 technical columns for everyone to lead you to learn together

"Billion-level traffic distributed system combat"

"Battery Factory Interview Must-Ask Series"

"Technical Talk"

"Zero Foundation takes you to learn java tutorial column"

"Take you to learn springCloud column"

"Take you to learn SpringCloud source code column"

"Take you to learn distributed system column"

"Take you to learn cloud native column"

"Take you to learn springboot source code"

"Take you to learn netty principles and practical column"

"Take you to learn Elasticsearch column"

"Take you to learn mysql column"

"Take you to learn JVM principle column"

"Take you to learn Redis principle column"

"Take you to learn java advanced column"

"Take you to learn big data column"

Introduction to Nacos

Nacos in Alibaba originated from the colorful stone project in 2008 (completed the split of microservices and the construction of business middle-end), grew up in the peak test of Double Eleven in ten years, and precipitated the core competitiveness of simplicity, stability and reliability, and excellent performance. . With the rise of cloud computing, we deeply felt the influence of the open source software industry in 2018, so we decided to open source Nacos (Alibaba's internal Configserver/Diamond/Vipserver kernel), export Alibaba's ten years of precipitation, promote the development of the microservice industry, and accelerate the digitalization of enterprises Transformation!
insert image description here

nacos practice

Learn Spring Cloud Alibaba in five minutes: Nacos is used as a registration center and configuration center

Architecture diagram

The overall architecture is divided into user layer, business layer, kernel layer and plug-ins. The user layer mainly solves the problem of ease of use by users, the business layer mainly solves the functional problems of service discovery and configuration management, and the kernel layer solves the consistency of distributed systems, For core problems such as storage and high availability, plug-ins solve scalability problems.
insert image description here

Source code analysis of this article

The use of thread pool in nacos

A large number of thread pools are used in nacos, such as protocol management, service subscription, etc. In order to achieve high availability and scalability, nacos code has unified processing for some common functions, and the code is more concise

First define a thread pool factory, which defines some public thread methods

public final class ExecutorFactory {
    
    
    
    public static ExecutorService newSingleExecutorService() {
    
    
        return Executors.newFixedThreadPool(1);
    }
    
    public static ExecutorService newSingleExecutorService(final ThreadFactory threadFactory) {
    
    
        return Executors.newFixedThreadPool(1, threadFactory);
    }
    
    public static ExecutorService newFixedExecutorService(final int nThreads) {
    
    
        return Executors.newFixedThreadPool(nThreads);
    }
    
    public static ExecutorService newFixedExecutorService(final int nThreads, final ThreadFactory threadFactory) {
    
    
        return Executors.newFixedThreadPool(nThreads, threadFactory);
    }
    
    public static ScheduledExecutorService newSingleScheduledExecutorService(final ThreadFactory threadFactory) {
    
    
        return Executors.newScheduledThreadPool(1, threadFactory);
    }
    
    public static ScheduledExecutorService newScheduledExecutorService(final int nThreads,
            final ThreadFactory threadFactory) {
    
    
        return Executors.newScheduledThreadPool(nThreads, threadFactory);
    }
    
    public static ThreadPoolExecutor newCustomerThreadExecutor(final int coreThreads, final int maxThreads,
            final long keepAliveTimeMs, final ThreadFactory threadFactory) {
    
    
        return new ThreadPoolExecutor(coreThreads, maxThreads, keepAliveTimeMs, TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<Runnable>(), threadFactory);
    }

Secondly, a more important class, ThreadPoolManager, this class mainly implements thread pool resource registration and destruction methods for other businesses to use

public final class ThreadPoolManager {
    
    
    
    private static final Logger LOGGER = LoggerFactory.getLogger(ThreadPoolManager.class);
    
    private Map<String, Map<String, Set<ExecutorService>>> resourcesManager;
    
    private Map<String, Object> lockers = new ConcurrentHashMap<String, Object>(8);
    
    private static final ThreadPoolManager INSTANCE = new ThreadPoolManager();
    
    private static final AtomicBoolean CLOSED = new AtomicBoolean(false);

    /**
     * 静态代码块初始化
     */
    static {
    
    
        //初始化存放线程池资源的Map,这里使用懒加载的思想
        INSTANCE.init();
        //这个是线程池工具类提供的一个钩子函数,用户结束线程池,addShutdownHook方法的作用是
        //当JVM关闭时,需要完成线程池中的任务,再关闭线程池,防止任务丢失
        ThreadUtils.addShutdownHook(new Thread(new Runnable() {
    
    
            @Override
            public void run() {
    
    
                LOGGER.warn("[ThreadPoolManager] Start destroying ThreadPool");
                shutdown();
                LOGGER.warn("[ThreadPoolManager] Destruction of the end");
            }
        }));
    }
    
    //获取当前类
    public static ThreadPoolManager getInstance() {
    
    
        return INSTANCE;
    }
    
    //实现私有构造器,不能继承
    private ThreadPoolManager() {
    
    
    }
    
    private void init() {
    
    
        //用的时候在进行初始化
        resourcesManager = new ConcurrentHashMap<String, Map<String, Set<ExecutorService>>>(8);
    }
    
    /**
     * Register the thread pool resources with the resource manager.
     *
     * @param namespace namespace name
     * @param group     group name
     * @param executor  {@link ExecutorService}
     */
    public void register(String namespace, String group, ExecutorService executor) {
    
    
        if (!resourcesManager.containsKey(namespace)) {
    
    
            //这里使用了synchronized,防止出现线程安全问题
            synchronized (this) {
    
    
                lockers.put(namespace, new Object());
            }
        }
        final Object monitor = lockers.get(namespace);
        synchronized (monitor) {
    
    
            Map<String, Set<ExecutorService>> map = resourcesManager.get(namespace);
            if (map == null) {
    
    
                map = new HashMap<String, Set<ExecutorService>>(8);
                map.put(group, new HashSet<ExecutorService>());
                map.get(group).add(executor);
                resourcesManager.put(namespace, map);
                return;
            }
            if (!map.containsKey(group)) {
    
    
                map.put(group, new HashSet<ExecutorService>());
            }
            map.get(group).add(executor);
        }
    }
    
    /**
     * Cancel the uniform lifecycle management for all threads under this resource.
     *
     * @param namespace namespace name
     * @param group     group name
     */
    public void deregister(String namespace, String group) {
    
    
        if (resourcesManager.containsKey(namespace)) {
    
    
            final Object monitor = lockers.get(namespace);
            synchronized (monitor) {
    
    
                resourcesManager.get(namespace).remove(group);
            }
        }
    }
    
    /**
     * Undoing the uniform lifecycle management of {@link ExecutorService} under this resource.
     *
     * @param namespace namespace name
     * @param group     group name
     * @param executor  {@link ExecutorService}
     */
    public void deregister(String namespace, String group, ExecutorService executor) {
    
    
        if (resourcesManager.containsKey(namespace)) {
    
    
            final Object monitor = lockers.get(namespace);
            synchronized (monitor) {
    
    
                final Map<String, Set<ExecutorService>> subResourceMap = resourcesManager.get(namespace);
                if (subResourceMap.containsKey(group)) {
    
    
                    subResourceMap.get(group).remove(executor);
                }
            }
        }
    }
    
    /**
     * Destroys all thread pool resources under this namespace.
     *
     * @param namespace namespace
     */
    public void destroy(final String namespace) {
    
    
        final Object monitor = lockers.get(namespace);
        if (monitor == null) {
    
    
            return;
        }
        synchronized (monitor) {
    
    
            Map<String, Set<ExecutorService>> subResource = resourcesManager.get(namespace);
            if (subResource == null) {
    
    
                return;
            }
            for (Map.Entry<String, Set<ExecutorService>> entry : subResource.entrySet()) {
    
    
                for (ExecutorService executor : entry.getValue()) {
    
    
                    ThreadUtils.shutdownThreadPool(executor);
                }
            }
            resourcesManager.get(namespace).clear();
            resourcesManager.remove(namespace);
        }
    }
    
    /**
     * This namespace destroys all thread pool resources under the grouping.
     *
     * @param namespace namespace
     * @param group     group
     */
    public void destroy(final String namespace, final String group) {
    
    
        final Object monitor = lockers.get(namespace);
        if (monitor == null) {
    
    
            return;
        }
        synchronized (monitor) {
    
    
            Map<String, Set<ExecutorService>> subResource = resourcesManager.get(namespace);
            if (subResource == null) {
    
    
                return;
            }
            Set<ExecutorService> waitDestroy = subResource.get(group);
            for (ExecutorService executor : waitDestroy) {
    
    
                ThreadUtils.shutdownThreadPool(executor);
            }
            resourcesManager.get(namespace).remove(group);
        }
    }
    
    /**
     * Shutdown thread pool manager.
     */
    public static void shutdown() {
    
    
    //使用乐观锁判断是否可以终止
        if (!CLOSED.compareAndSet(false, true)) {
    
    
            return;
        }
        Set<String> namespaces = INSTANCE.resourcesManager.keySet();
        for (String namespace : namespaces) {
    
    
            INSTANCE.destroy(namespace);
        }
    }
    
}

The following is the tool class ThreadUtils that we can use out of the source code

package com.alibaba.nacos.common.utils;

import org.slf4j.Logger;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * Thread utils.
 *
 * @author <a href="mailto:[email protected]">liaochuntao</a>
 */
public final class ThreadUtils {
    
    
    
    /**
     * Wait.
     *
     * @param object load object
     */
    public static void objectWait(Object object) {
    
    
        try {
    
    
            object.wait();
        } catch (InterruptedException ignore) {
    
    
            Thread.interrupted();
        }
    }
    
    /**
     * Sleep.
     *
     * @param millis sleep millisecond
     */
    public static void sleep(long millis) {
    
    
        try {
    
    
            Thread.sleep(millis);
        } catch (InterruptedException e) {
    
    
            Thread.currentThread().interrupt();
        }
    }
    
    public static void countDown(CountDownLatch latch) {
    
    
        Objects.requireNonNull(latch, "latch");
        latch.countDown();
    }
    
    /**
     * Await count down latch.
     *
     * @param latch count down latch
     */
    public static void latchAwait(CountDownLatch latch) {
    
    
        try {
    
    
            latch.await();
        } catch (InterruptedException e) {
    
    
            Thread.currentThread().interrupt();
        }
    }
    
    /**
     * Await count down latch with timeout.
     *
     * @param latch count down latch
     * @param time  timeout time
     * @param unit  time unit
     */
    public static void latchAwait(CountDownLatch latch, long time, TimeUnit unit) {
    
    
        try {
    
    
            latch.await(time, unit);
        } catch (InterruptedException e) {
    
    
            Thread.currentThread().interrupt();
        }
    }
    
    /**
     * Through the number of cores, calculate the appropriate number of threads; 1.5-2 times the number of CPU cores.
     *
     * @return thread count
     */
    public static int getSuitableThreadCount() {
    
    
        return getSuitableThreadCount(THREAD_MULTIPLER);
    }
    
    /**
     * Through the number of cores, calculate the appropriate number of threads.
     *
     * @param threadMultiple multiple time of cores
     * @return thread count
     */
    public static int getSuitableThreadCount(int threadMultiple) {
    
    
        final int coreCount = Runtime.getRuntime().availableProcessors();
        int workerCount = 1;
        while (workerCount < coreCount * threadMultiple) {
    
    
            workerCount <<= 1;
        }
        return workerCount;
    }
    
    public static void shutdownThreadPool(ExecutorService executor) {
    
    
        shutdownThreadPool(executor, null);
    }
    
    /**
     * Shutdown thread pool.
     *
     * @param executor thread pool
     * @param logger   logger
     */
    public static void shutdownThreadPool(ExecutorService executor, Logger logger) {
    
    
        executor.shutdown();
        //重试策略
        int retry = 3;
        while (retry > 0) {
    
    
            retry--;
            try {
    
    
                if (executor.awaitTermination(1, TimeUnit.SECONDS)) {
    
    
                    return;
                }
            } catch (InterruptedException e) {
    
    
                executor.shutdownNow();
                Thread.interrupted();
            } catch (Throwable ex) {
    
    
                if (logger != null) {
    
    
                    logger.error("ThreadPoolManager shutdown executor has error : {}", ex);
                }
            }
        }
        executor.shutdownNow();
    }
    
    public static void addShutdownHook(Runnable runnable) {
    
    
        Runtime.getRuntime().addShutdownHook(new Thread(runnable));
    }
    
    private static final int THREAD_MULTIPLER = 2;
    
}

Everyone must remember to like, subscribe, and follow

Prevent it from being found next time

Your support is the driving force for me to continue to create! ! !

Guess you like

Origin blog.csdn.net/weixin_44302240/article/details/123501326