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

com.huaweicloud.dws.client.worker.ExecutionPool Maven / Gradle / Ivy

package com.huaweicloud.dws.client.worker;

import com.huaweicloud.dws.client.DwsClient;
import com.huaweicloud.dws.client.DwsConfig;
import com.huaweicloud.dws.client.action.AbstractAction;
import com.huaweicloud.dws.client.action.GetAction;
import com.huaweicloud.dws.client.action.ScanAction;
import com.huaweicloud.dws.client.action.WriteAction;
import com.huaweicloud.dws.client.collector.ActionCollector;
import com.huaweicloud.dws.client.exception.DwsClientException;
import com.huaweicloud.dws.client.exception.ExceptionCode;
import com.huaweicloud.dws.client.op.Get;
import lombok.extern.slf4j.Slf4j;

import java.io.Closeable;
import java.io.IOException;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @ProjectName: dws-connector
 * @ClassName: ExecutionPool
 * @Description: 资源池
 * @Date: 2023/1/9 19:06
 * @Version: 1.0
 */
@Slf4j
public class ExecutionPool implements Closeable {

    public static final long AWAIT_TIME = 500L;

    private final String name;

    /**
     * 所有的执行者(按照并发,每个初始化一个执行者)
     */
    private final ActionExecutor[] executors;

    /**
     * 后台任务执行
     */
    private final BackgroundExecutor backgroundJob;
    private final WaitActionTaskExecutor waitActionTask;
    private final ReadActionExecutor readActionJob;

    /**
     * 配置
     */
    private final DwsConfig config;

    /**
     * 是否在运行
     */
    private final AtomicBoolean started;
    private final AtomicBoolean flushing;

    /**
     * 执行任务线程池
     */
    private ExecutorService workerExecutorService;
    private final ThreadFactory workerThreadFactory;

    /**
     * 后台任务线程池
     */
    private ExecutorService backgroundExecutorService;
    private final ThreadFactory backgroundThreadFactory;

    private final ActionCollector collector;
    private final ArrayBlockingQueue queue;

    public ActionCollector getCollector() {
        return collector;
    }

    public ArrayBlockingQueue getQueue() {
        return queue;
    }

    /**
     * 检查状态是否能够正常使用资源池,如果不允许使用则阻塞业务线程
     */
    public void checkStatus() throws DwsClientException {
        if (!flushing.get()) {
            return;
        }
        // 在强制执行刷库任务期间 阻塞写入
        log.info("wait flush end.");
        try {
            synchronized (flushing) {
                while (flushing.get()) {
                    flushing.wait();
                }
            }
        } catch (Exception e) {
            throw DwsClientException.fromException(e);
        }
        log.info("end wait flush end.");
    }

    /**
     * 强制刷资源池中的任
     */
    public void flush() throws DwsClientException {
        synchronized (flushing) {
            try {
                flushing.set(true);
                // 所有收集器中的缓存提交资源池执行
                collector.flush();
                // 等待资源池中任务全部执行完成
                waitActionTask.flush();
            } finally {
                flushing.set(false);
                flushing.notifyAll();
            }
        }
    }

    public ExecutionPool(String name, DwsConfig config, DwsClient client) {
        this.name = name;
        this.config = config;
        this.queue = new ArrayBlockingQueue<>(config.getReadBatchQueueSize());
        this.collector = new ActionCollector(config, this);
        workerThreadFactory = new ThreadFactory() {
            private final AtomicInteger threadNumber = new AtomicInteger(1);

            @Override
            public Thread newThread(Runnable r) {
                Thread t = new Thread(r);
                t.setName(name + "-worker-" + threadNumber.getAndIncrement());
                t.setDaemon(true);
                return t;
            }
        };

        backgroundThreadFactory = new ThreadFactory() {
            private final AtomicInteger threadNumber = new AtomicInteger(1);

            @Override
            public Thread newThread(Runnable r) {
                Thread t = new Thread(r);
                t.setName(name + "-background-" + threadNumber.getAndIncrement());
                t.setDaemon(true);
                return t;
            }
        };
        started = new AtomicBoolean(false);
        flushing = new AtomicBoolean(false);
        waitActionTask = new WaitActionTaskExecutor(config, started, client);
        backgroundJob = new BackgroundExecutor(config, started, collector, client);
        readActionJob = new ReadActionExecutor(config, started, collector, client, config.getReadBatchSize());
        int workerSize = Math.max(config.getThreadSize(), config.getReadThreadSize());
        executors = new ActionExecutor[workerSize];
        for (int i = 0; i < workerSize; i++) {
            executors[i] = new ActionExecutor(started, config);
        }
        start();
    }

    private synchronized void start() {
        if (started.compareAndSet(false, true)) {
            log.info("Execution Pool start name = {}", name);
            // 初始化线程池
            workerExecutorService = new ThreadPoolExecutor(executors.length, executors.length, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(1), workerThreadFactory, new ThreadPoolExecutor.AbortPolicy());
            backgroundExecutorService = new ThreadPoolExecutor(3, 3, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(1), backgroundThreadFactory, new ThreadPoolExecutor.AbortPolicy());
            for (int i = 0; i < executors.length; i++) {
                // 把每个干活的都拉起来
                workerExecutorService.execute(executors[i]);
            }
            // 后台任务开始跑起来
            backgroundExecutorService.execute(backgroundJob);
            backgroundExecutorService.execute(readActionJob);
            backgroundExecutorService.execute(waitActionTask);
            // 系统停止时执行关闭
            /**
             * 程序关闭时回调任务
             */
            if (config.isAutoCloseDwsClient()) {
                Runtime.getRuntime().addShutdownHook(new Thread(this::close));
            }
        }
    }

    public boolean isRunning() {
        return started.get();
    }

    public boolean submit(AbstractAction action) throws DwsClientException {
        return submit(action, false);
    }

    /**
     * @param isSync 是否异步,异步直接会放入后台监听、获取执行结果
     * @return
     * @throws DwsClientException
     */
    public boolean submit(AbstractAction action, boolean isSync) throws DwsClientException {
        // 已经close的不允许提交
        if (!isRunning()) {
            throw new DwsClientException(ExceptionCode.ALREADY_CLOSE, "this pool is closed.");
        }
        int start;
        int end;
        if (action instanceof WriteAction) {
            start = 0;
            end = Math.min(config.getThreadSize(), executors.length);
        } else if (action instanceof GetAction || action instanceof ScanAction) {
            start = Math.max(0, executors.length - config.getReadThreadSize());
            end = executors.length;
        } else {
            start = 0;
            end = executors.length;
        }
        // 尝试在每个任务执行器上提交执行
        for (int i = start; i < end; ++i) {
            ActionExecutor executor = executors[i];
            // 寻找一个空闲的executor 执行该任务
            if (executor.submit(action)) {
                if (isSync) {
                    waitActionTask.submitAction(action);
                }
                return true;
            }
        }
        return false;
    }

    /**
     * 检查后台任务是否有异常
     */
    public void tryException() throws DwsClientException {
        backgroundJob.tryException();
        readActionJob.tryException();
        waitActionTask.tryException();
    }


    public void waitAction(AbstractAction action) {
        waitActionTask.submitAction(action);
    }

    @Override
    public void close() {
        try {
            // 先停止后台任务后再关闭资源
            backgroundJob.close();
            readActionJob.close();
            waitActionTask.close();
        } catch (IOException e) {
            log.error("", e);
        }
        if (started.compareAndSet(true, false)) {
            for (ActionExecutor executor : executors) {
                try {
                    executor.close();
                } catch (IOException e) {
                    log.error("", e);
                }
            }
            try {
                backgroundExecutorService.shutdown();
                while (!backgroundExecutorService.awaitTermination(AWAIT_TIME, TimeUnit.MILLISECONDS)) {
                    log.info("wait background executorService termination[{}]", name);
                }
            } catch (Exception e) {
                log.error("shutdown background error.", e);
            }
            backgroundExecutorService = null;
            try {
                workerExecutorService.shutdown();
                while (!workerExecutorService.awaitTermination(AWAIT_TIME, TimeUnit.MILLISECONDS)) {
                    log.info("wait worker executorService termination[{}]", name);
                }
                workerExecutorService = null;
            } catch (Exception e) {
                log.error("shutdown worker error.", e);
            }
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy