当前位置:

首页 > 编程开发 > 怎么使用Java实现多任务执行助手

怎么使用Java实现多任务执行助手

1.多线程执行任务类packagecom.visy.threadpool;importcom.visy.executor.ExecutorFactory;importjava.util.ArrayList;importjava.util.Iterator;importjava.util.List;importjava.util.concurrent.Callable;importjava.util.concurrent.ExecutionException;importjava.util.concurre

本文目录

    1.多线程执行任务类

    package com.visy.threadpool;
    
    import com.visy.executor.ExecutorFactory;
    import java.util.ArrayList;
    import java.util.Iterator;
    import java.util.List;
    import java.util.concurrent.Callable;
    import java.util.concurrent.ExecutionException;
    import java.util.concurrent.Future;
    import java.util.concurrent.ThreadPoolExecutor;
    import java.util.concurrent.TimeUnit;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    public class ThreadPoolConfig {
        private TheadPoolProperties theadPoolProperties;
        private ThreadPoolExecutor executor;
        private ThreadPoolExecutor executorChild;
    
        public ThreadPoolConfig(TheadPoolProperties theadPoolProperties) {
            this.theadPoolProperties = theadPoolProperties;
            this.executor = ExecutorFactory.getInstance().getThreadPoolExecutor("ThreadPoolConfig-service", theadPoolProperties.getQueueSize(), theadPoolProperties.getCoreThreadNum(), theadPoolProperties.getMaxPoolSize());
            this.executorChild = ExecutorFactory.getInstance().getThreadPoolExecutor("ThreadPoolConfig-service-child", theadPoolProperties.getQueueSize(), theadPoolProperties.getCoreThreadNum(), theadPoolProperties.getMaxPoolSize());
        }
    
        public  List doConcurrentTask(List> taskList, ThreadPoolExecutor... executorChilds) {
            if (taskList != null && !taskList.isEmpty()) {
                List resultList = new ArrayList();
                List futureList = null;
    
                try {
                    if (this.executor.getQueue().size() >= this.theadPoolProperties.getQueueSize()) {
                        throw new RuntimeException("queue size bigger than 100, now size is " + this.executor.getQueue().size());
                    }
    
                    if (executorChilds != null && executorChilds.length > 0 && executorChilds[0] != null) {
                        futureList = executorChilds[0].invokeAll(taskList);
                    } else {
                        futureList = this.executor.invokeAll(taskList, (long)this.theadPoolProperties.getTimeOut(), TimeUnit.SECONDS);
                    }
                } catch (InterruptedException var6) {
                    var6.printStackTrace();
                }
    
                this.doFutureList(resultList, futureList);
                return resultList;
            } else {
                return null;
            }
        }
    
         void doFutureList(List resultList, List> futureList) {
            if (futureList != null) {
                Iterator var3 = futureList.iterator();
    
                while(var3.hasNext()) {
                    Future future = (Future)var3.next();
    
                    try {
                        resultList.add(future.get());
                    } catch (ExecutionException | InterruptedException var6) {
                        var6.printStackTrace();
                    }
                }
            }
    
        }
    
        public  void doVoidConcurrentTask(List> taskList) {
            if (taskList != null && !taskList.isEmpty()) {
                Iterator var2 = taskList.iterator();
    
                while(var2.hasNext()) {
                    Callable call = (Callable)var2.next();
                    this.executor.submit(call);
                }
    
            }
        }
    
        public TheadPoolProperties getTheadPoolProperties() {
            return this.theadPoolProperties;
        }
    
        public ThreadPoolExecutor getExecutor() {
            return this.executor;
        }
    
        public ThreadPoolExecutor getExecutorChild() {
            return this.executorChild;
        }
    
        public void setTheadPoolProperties(TheadPoolProperties theadPoolProperties) {
            this.theadPoolProperties = theadPoolProperties;
        }
    
        public void setExecutor(ThreadPoolExecutor executor) {
            this.executor = executor;
        }
    
        public void setExecutorChild(ThreadPoolExecutor executorChild) {
            this.executorChild = executorChild;
        }
    
        public boolean equals(Object o) {
            if (o == this) {
                return true;
            } else if (!(o instanceof ThreadPoolConfig)) {
                return false;
            } else {
                ThreadPoolConfig other = (ThreadPoolConfig)o;
                if (!other.canEqual(this)) {
                    return false;
                } else {
                    label47: {
                        Object this$theadPoolProperties = this.getTheadPoolProperties();
                        Object other$theadPoolProperties = other.getTheadPoolProperties();
                        if (this$theadPoolProperties == null) {
                            if (other$theadPoolProperties == null) {
                                break label47;
                            }
                        } else if (this$theadPoolProperties.equals(other$theadPoolProperties)) {
                            break label47;
                        }
    
                        return false;
                    }
    
                    Object this$executor = this.getExecutor();
                    Object other$executor = other.getExecutor();
                    if (this$executor == null) {
                        if (other$executor != null) {
                            return false;
                        }
                    } else if (!this$executor.equals(other$executor)) {
                        return false;
                    }
    
                    Object this$executorChild = this.getExecutorChild();
                    Object other$executorChild = other.getExecutorChild();
                    if (this$executorChild == null) {
                        if (other$executorChild != null) {
                            return false;
                        }
                    } else if (!this$executorChild.equals(other$executorChild)) {
                        return false;
                    }
    
                    return true;
                }
            }
        }
    
        protected boolean canEqual(Object other) {
            return other instanceof ThreadPoolConfig;
        }
    
        public int hashCode() {
            int PRIME = true;
            int result = 1;
            Object $theadPoolProperties = this.getTheadPoolProperties();
            int result = result * 59 + ($theadPoolProperties == null ? 43 : $theadPoolProperties.hashCode());
            Object $executor = this.getExecutor();
            result = result * 59 + ($executor == null ? 43 : $executor.hashCode());
            Object $executorChild = this.getExecutorChild();
            result = result * 59 + ($executorChild == null ? 43 : $executorChild.hashCode());
            return result;
        }
    
        public String toString() {
            return "ThreadPoolConfig(theadPoolProperties=" + this.getTheadPoolProperties() + ", executor=" + this.getExecutor() + ", executorChild=" + this.getExecutorChild() + ")";
        }
    }

    2.执行器工厂类

    package com.visy.executor;
    
    import java.util.Map;
    import java.util.concurrent.Callable;
    import java.util.concurrent.ConcurrentHashMap;
    import java.util.concurrent.Future;
    import java.util.concurrent.ThreadPoolExecutor;
    import org.apache.commons.lang.StringUtils;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    public class ExecutorFactory {
        private static final Logger logger = LoggerFactory.getLogger(ExecutorFactory.class);
        private static final Map threadPoolExecutorMap = new ConcurrentHashMap();
        private static final int DEFAULT_QUEUE_SIZE = 1000;
        private static final String DEFAULT_EXECUTOR_NAME = "default-executor";
        private static final int MAX_THREAD_NUM = 100;
        private static final int CORE_THREAD_NUM = 1;
        private static volatile ExecutorFactory instance;
    
        private ExecutorFactory() {
        }
    
        public static ExecutorFactory getInstance() {
            if (instance == null) {
                Class var0 = ExecutorFactory.class;
                synchronized(ExecutorFactory.class) {
                    if (instance == null) {
                        instance = new ExecutorFactory();
                    }
                }
            }
    
            return instance;
        }
    
        public ThreadPoolExecutor getThreadPoolExecutorByName(String name) {
            return (ThreadPoolExecutor)threadPoolExecutorMap.get(name);
        }
    
        public static Map getThreadPoolExecutorMap() {
            return threadPoolExecutorMap;
        }
    
        public ThreadPoolExecutor getThreadPoolExecutor(String threadPoolExecutorName, int queueSize, int coreThreadNum, int maxPoolSize) {
            if (StringUtils.isBlank(threadPoolExecutorName)) {
                throw new IllegalArgumentException("thread name empty");
            } else {
                if (!threadPoolExecutorMap.containsKey(threadPoolExecutorName)) {
                    Class var5 = ExecutorFactory.class;
                    synchronized(ExecutorFactory.class) {
                        if (!threadPoolExecutorMap.containsKey(threadPoolExecutorName)) {
                            ThreadPoolExecutor executor = (new ThreadPool(coreThreadNum, maxPoolSize, 30L, queueSize, threadPoolExecutorName)).getExecutor();
                            threadPoolExecutorMap.put(threadPoolExecutorName, executor);
                            logger.info("thread name: {} executor created", threadPoolExecutorName);
                        }
                    }
                }
    
                return (ThreadPoolExecutor)threadPoolExecutorMap.get(threadPoolExecutorName);
            }
        }
    
        public  void submit(T t) {
            ThreadPoolExecutor defaultExecutor = this.getThreadPoolExecutor();
            defaultExecutor.submit(t);
        }
    
        public  void submit(String poolName, T t) {
            ThreadPoolExecutor executor = this.getThreadPoolExecutorByName(poolName);
            if (executor == null) {
                logger.error("thread name: {} executor not exist.", poolName);
                throw new IllegalArgumentException("thread name:" + poolName + " executor not exist.");
            } else {
                executor.submit(t);
            }
        }
    
        public > Future submit(T t) {
            ThreadPoolExecutor defaultExecutor = this.getThreadPoolExecutor();
            return defaultExecutor.submit(t);
        }
    
        public > Future submit(String poolName, T t) {
            ThreadPoolExecutor executor = this.getThreadPoolExecutorByName(poolName);
            if (executor == null) {
                logger.error("thread poolName: {} executor not exist.", poolName);
                throw new IllegalArgumentException("thread poolName:" + poolName + " executor not exist.");
            } else {
                return executor.submit(t);
            }
        }
    
        public ThreadPoolExecutor getThreadPoolExecutor() {
            return this.getThreadPoolExecutor("default-executor", 1000, 1, 100);
        }
    }

    3.多线程配置类

    package com.visy.threadpool;
    
    import javax.validation.constraints.NotNull;
    import org.springframework.boot.context.properties.ConfigurationProperties;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.validation.annotation.Validated;
    
    @Validated
    @Configuration
    @ConfigurationProperties(prefix = "visy.threadpool")
    public class TheadPoolProperties {
        // 执行并行任务时,等待多久时间超时(单位:秒)
        @NotNull
        private Integer timeOut;
        // 队列大小
        @NotNull
        private Integer queueSize; 
        // 核心线程数量
        @NotNull
        private Integer coreThreadNum;
        // 线程池最大线程数量
        @NotNull
        private Integer maxPoolSize;
        // 并行执行每组大小
        private Integer groupSize = 20;
    
        public TheadPoolProperties() {
        }
    
        public Integer getTimeOut() {
            return this.timeOut;
        }
    
        public Integer getQueueSize() {
            return this.queueSize;
        }
    
        public Integer getCoreThreadNum() {
            return this.coreThreadNum;
        }
    
        public Integer getMaxPoolSize() {
            return this.maxPoolSize;
        }
    
        public Integer getGroupSize() {
            return this.groupSize;
        }
    
        public void setTimeOut(Integer timeOut) {
            this.timeOut = timeOut;
        }
    
        public void setQueueSize(Integer queueSize) {
            this.queueSize = queueSize;
        }
    
        public void setCoreThreadNum(Integer coreThreadNum) {
            this.coreThreadNum = coreThreadNum;
        }
    
        public void setMaxPoolSize(Integer maxPoolSize) {
            this.maxPoolSize = maxPoolSize;
        }
    
        public void setGroupSize(Integer groupSize) {
            this.groupSize = groupSize;
        }
    
        public boolean equals(Object o) {
            if (o == this) {
                return true;
            } else if (!(o instanceof TheadPoolProperties)) {
                return false;
            } else {
                TheadPoolProperties other = (TheadPoolProperties)o;
                if (!other.canEqual(this)) {
                    return false;
                } else {
                    label71: {
                        Object this$timeOut = this.getTimeOut();
                        Object other$timeOut = other.getTimeOut();
                        if (this$timeOut == null) {
                            if (other$timeOut == null) {
                                break label71;
                            }
                        } else if (this$timeOut.equals(other$timeOut)) {
                            break label71;
                        }
    
                        return false;
                    }
    
                    Object this$queueSize = this.getQueueSize();
                    Object other$queueSize = other.getQueueSize();
                    if (this$queueSize == null) {
                        if (other$queueSize != null) {
                            return false;
                        }
                    } else if (!this$queueSize.equals(other$queueSize)) {
                        return false;
                    }
    
                    label57: {
                        Object this$coreThreadNum = this.getCoreThreadNum();
                        Object other$coreThreadNum = other.getCoreThreadNum();
                        if (this$coreThreadNum == null) {
                            if (other$coreThreadNum == null) {
                                break label57;
                            }
                        } else if (this$coreThreadNum.equals(other$coreThreadNum)) {
                            break label57;
                        }
    
                        return false;
                    }
    
                    Object this$maxPoolSize = this.getMaxPoolSize();
                    Object other$maxPoolSize = other.getMaxPoolSize();
                    if (this$maxPoolSize == null) {
                        if (other$maxPoolSize != null) {
                            return false;
                        }
                    } else if (!this$maxPoolSize.equals(other$maxPoolSize)) {
                        return false;
                    }
    
                    Object this$groupSize = this.getGroupSize();
                    Object other$groupSize = other.getGroupSize();
                    if (this$groupSize == null) {
                        if (other$groupSize == null) {
                            return true;
                        }
                    } else if (this$groupSize.equals(other$groupSize)) {
                        return true;
                    }
    
                    return false;
                }
            }
        }
    
        protected boolean canEqual(Object other) {
            return other instanceof TheadPoolProperties;
        }
    
        public int hashCode() {
            int PRIME = true;
            int result = 1;
            Object $timeOut = this.getTimeOut();
            int result = result * 59 + ($timeOut == null ? 43 : $timeOut.hashCode());
            Object $queueSize = this.getQueueSize();
            result = result * 59 + ($queueSize == null ? 43 : $queueSize.hashCode());
            Object $coreThreadNum = this.getCoreThreadNum();
            result = result * 59 + ($coreThreadNum == null ? 43 : $coreThreadNum.hashCode());
            Object $maxPoolSize = this.getMaxPoolSize();
            result = result * 59 + ($maxPoolSize == null ? 43 : $maxPoolSize.hashCode());
            Object $groupSize = this.getGroupSize();
            result = result * 59 + ($groupSize == null ? 43 : $groupSize.hashCode());
            return result;
        }
    
        public String toString() {
            return "TheadPoolProperties(timeOut=" + this.getTimeOut() + ", queueSize=" + this.getQueueSize() + ", coreThreadNum=" + this.getCoreThreadNum() + ", maxPoolSize=" + this.getMaxPoolSize() + ", groupSize=" + this.getGroupSize() + ")";
        }
    }

    4.列表拆分工具类

    package com.visy.utils;
    
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.List;
    import java.util.jar.Attributes;
    
    /**
     * 列表或数组按指定大小分组,用于批量取一部分数据循环处理
     *
     */
    public class ArraySplitUtil {
        /**
         * 按指定大小对列表分组
         * @param list
         * @param splitSize
         * @return
         */
        public List> splistList(List list, int splitSize) {
            if (null == list || list.size() == 0) {
                return null;
            }
            int listSize = list.size();
            List> newList = new ArrayList<>();
            if (listSize < splitSize) {
                newList.add(list);
                return newList;
            }
            int addLength = splitSize;
            int times = listSize / splitSize;
            if (listSize % splitSize != 0) {
                times += 1;
            }
            int start = 0;
            int end = 0;
            int last = times - 1;
            for (int i = 0; i < times; i++) {
                start = i * splitSize;
                if (i < last) {
                    end = start + addLength;
                } else {
                    end = listSize;
                }
                newList.add(list.subList(start, end));
            }
            return newList;
        }
    
        /**
         * 按指定大小对数组分组
         * @param array
         * @param splitSize
         * @return
         */
        public List splistArray(T[] array, int splitSize) {
            if (null == array) {
                return null;
            }
            int listSize = array.length;
            List newList = new ArrayList<>();
            if (listSize < splitSize) {
                newList.add(array);
                return newList;
            }
            int addLength = splitSize;
            int times = listSize / splitSize;
            if (listSize % splitSize != 0) {
                times += 1;
            }
            int start = 0;
            int end = 0;
            int last = times - 1;
            for (int i = 0; i < times; i++) {
                start = i * splitSize;
                if (i < last) {
                    end = start + addLength;
                } else {
                    end = listSize;
                }
                newList.add(Arrays.copyOfRange(array, start, end));
            }
            return newList;
        }
    
        public static  ArraySplitUtil build(){
            return new ArraySplitUtil<>();
        }
    }

    5.多任务执行助手类

    package com.visy.helper;
    
    import com.baomidou.mybatisplus.toolkit.CollectionUtils;
    import com.google.common.collect.Lists;
    import com.visy.utils.ArraySplitUtil;
    import com.visy.threadpool.ThreadPoolConfig;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    import java.util.List;
    import java.util.Map;
    import java.util.Objects;
    import java.util.concurrent.Callable;
    import java.util.concurrent.ConcurrentHashMap;
    import java.util.function.Consumer;
    import java.util.function.Function;
    import java.util.stream.Collectors;
    
    /**
     * 多任务助手
     * @author visy.wang
     * @date 2022/5/9 14:38
     */
    @Service
    public class MultiTaskHelper {
        @Autowired
        private ThreadPoolConfig threadPoolConfig;
        private static final Map> ArraySplitUtilCache = new ConcurrentHashMap<>();
    
        public  List> createAndRunListTask(List list, Function handler){
            return createAndRunListTask(list, null, handler);
        }
    
        public  List> createAndRunListTaskV2(List list, Function, List> handler){
            return createAndRunListTask(list, handler, null);
        }
    
        public  void createAndRunListTaskWithoutReturn(List list, Consumer handler){
            createAndRunListTaskWithoutReturn(list, null, handler);
        }
    
        public  void createAndRunListTaskWithoutReturnV2(List list, Consumer> handler){
            createAndRunListTaskWithoutReturn(list, handler, null);
        }
    
        /**
         * 把列表按线程数分组
         * @param list 列表
         * @return 分组后的列表
         */
        @SuppressWarnings("unchecked")
        private  List> listSplit(List list){
            String key = list.get(0).getClass().getName();
            int groupSize = threadPoolConfig.getTheadPoolProperties().getGroupSize();
            ArraySplitUtil arraySplitUtil = (ArraySplitUtil)ArraySplitUtilCache.get(key);
            if(Objects.isNull(arraySplitUtil)){
                arraySplitUtil = ArraySplitUtil.build();
                ArraySplitUtilCache.put(key, arraySplitUtil);
            }
            return arraySplitUtil.splistList(list, groupSize);
        }
    
        /**
         * 创建并运行多任务
         * @param list 输入数据列表
         * @param handler1 处理器1 (优先级使用)
         * @param handler2 处理器2
         * @param  输入数据类型
         * @param  输出数据类型
         * @return 执行结果分组列表
         */
        private  List> createAndRunListTask(List list,  Function, List> handler1, Function handler2){
            List> listGroup = listSplit(list);
            //设定每个组的任务
            List>> taskList = Lists.newArrayListWithExpectedSize(listGroup.size());
            listGroup.stream().filter(CollectionUtils::isNotEmpty).forEach(subList -> {
                taskList.add(() -> {
                    if(Objects.nonNull(handler1)){
                        return handler1.apply(subList);
                    }else if(Objects.nonNull(handler2)){
                        return subList.stream().map(handler2).collect(Collectors.toList());
                    }else{
                        return null;
                    }
                });
            });
            return threadPoolConfig.doConcurrentTask(taskList);
        }
    
        /**
         * 创建并运行多任务(无返回结果)
         * @param list 输入数据列表
         * @param handler1 处理器1 (优先级更高)
         * @param handler2 处理器2
         * @param  输入数据类型
         */
        private  void createAndRunListTaskWithoutReturn(List list, Consumer> handler1, Consumer handler2){
            List> listGroup = listSplit(list);
            //设定每个组的任务
            List>> taskList = Lists.newArrayListWithExpectedSize(listGroup.size());
            listGroup.stream().filter(CollectionUtils::isNotEmpty).forEach(subList -> {
                taskList.add(() -> {
                    if(Objects.nonNull(handler1)){
                        handler1.accept(subList);
                    }else if(Objects.nonNull(handler2)){
                        subList.forEach(handler2);
                    }
                    return null;
                });
            });
            threadPoolConfig.doConcurrentTask(taskList);
        }
    }

    6.多任务助手使用:

    @Autowired
    package com.zoom.fleet.schedule.service;
    
    import com.visy.helper.MultiTaskHelper;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    import java.util.ArrayList;
    import java.util.List;
    import java.util.stream.Collectors;
    
    /**
     * 多任务助手使用示例
     * @author visy.wang
     * @date 2022/5/13 14:11
     */
    @Service
    public class MultiTaskTest {
        @Autowired
        private MultiTaskHelper multiTaskHelper;
    
        private void test(){
    
            //待多任务执行的数据列表
            List idList = new ArrayList<>();
    
            //1.有返回结果的执行方式一, 定义单个数据的处理逻辑,返回多任务执行结果和合集
            List> resultList = multiTaskHelper.createAndRunListTask(idList, id->{
                //每一项数据的业务代码
                return Long.valueOf(id);
            });
    
            //2.有返回结果的执行方式二, 定义单个数线程的处理逻辑,返回多任务执行结果和合集
            resultList = multiTaskHelper.createAndRunListTaskV2(idList, subIdList->{
                //每一个线程下列表操作的业务代码
                return subIdList.stream().map(id->{
                    //每一项数据的业务代码
                    return Long.valueOf(id);
                }).collect(Collectors.toList());
            });
    
            //3.无返回结果的执行方式一, 定义单个数据的处理逻辑
            multiTaskHelper.createAndRunListTaskWithoutReturn(idList, id->{
                //每一项数据的业务代码...
            });
    
            //3.无返回结果的执行方式一, 定义单个数据的处理逻辑
            multiTaskHelper.createAndRunListTaskWithoutReturnV2(idList, subIdList->{
                subIdList.forEach(id->{
                    //每一项数据的业务代码...
                });
                //继续操作subIdList...
            });
        }
    }
    本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系bd@zhengruan.com
    作者最新文章
    编程开发 Java
    相关文章 更多
    Java单元测试入门:使用JUnit 5编写第一个测试用例
    Java单元测试入门:使用JUnit 5编写第一个测试用例

    面向初学者的JUnit 5实用入门指南。从测试概念、Maven依赖配置,到手把手编写首个单元测试用例及断言验证,助你掌握Java单元测试的核心流程。

    Java变量未初始化报错解析:局部变量与成员变量默认值差异
    Java变量未初始化报错解析:局部变量与成员变量默认值差异

    深入解析Java中局部变量未初始化编译报错与成员变量自动赋予默认值的机制差异,涵盖JVM内存分配、编译期确定性赋值检查与实际排查修复方案。

    Java获取当前时间并格式化输出:DateTimeFormatter与SimpleDateFormat
    Java获取当前时间并格式化输出:DateTimeFormatter与SimpleDateFormat

    详细讲解在Java中获取当前系统时间并进行格式化输出的两种核心方案:基于Java 8全新日期时间API的DateTimeFormatter与传统遗留的SimpleDateFormat,包含完整代码示例、线程安全机制对比及生产选型建议。

    Java中final与static final常量的定义及初始化规则
    Java中final与static final常量的定义及初始化规则

    深入解析Java中final变量与static final常量的定义、内存语义、初始化时机及合法赋值路径,涵盖编译期常量优化与实战避坑指南。

    Java抽象方法与接口方法的区别及选型建议
    Java抽象方法与接口方法的区别及选型建议

    深入对比Java中抽象类抽象方法与接口方法的语法演进、设计意图及运行期差异,并提供清晰的架构选型决策流程与实战范例。

    Java实现HTTP请求与JSON解析的完整代码示例
    Java实现HTTP请求与JSON解析的完整代码示例

    本文提供Java标准库HttpClient发起HTTP GET/POST请求并结合Jackson进行JSON数据反序列化与序列化的完整代码示例与工程实践指南。

    Java递归出现StackOverflowError的原因分析及栈空间优化方案
    Java递归出现StackOverflowError的原因分析及栈空间优化方案

    详细分析Java递归调用出现StackOverflowError的原因,结合代码说明线程栈、栈帧和递归深度之间的关系,并介绍终止条件排查、迭代改写、减少栈帧开销以及通过-Xss调整JVM栈空间的方法。

    Java空指针异常(NPE)的代码排查与修复实例
    Java空指针异常(NPE)的代码排查与修复实例

    针对Java中常见的NullPointerException(NPE),本文从堆栈日志定位、典型代码触发场景、具体修复代码对比到防御体系进行系统讲解,提供实用且易上手的排查与修复方案。

    selenium上传文件教程本地文件路径设置方法
    selenium上传文件教程本地文件路径设置方法

    深入解析Selenium处理文件上传的技术细节,涵盖标准HTML控件的路径直接注入法与非标准控件的系统级模拟方案,提供Windows与Linux环境下的路径设置最佳实践及常见异常排查。

    大数据开发语言选型:Java对比Scala与Python的优缺点及适用场景
    大数据开发语言选型:Java对比Scala与Python的优缺点及适用场景

    针对大数据工程场景,系统对比Java、Scala与Python在执行性能、生态结合、开发效率和维护成本上的核心差异,给出清晰的架构选型依据与落地方案。

    查看更多
    精品专题 更多
    装机必备
    装机必备

    正软商城装机必备专区,精选办公、浏览器、安全防护、影音播放、压缩解压、设计创作和系统工具等电脑常用正版软件,帮助用户快速完成新电脑软件配置。

    Windows
    Windows

    正软商城Windows软件专区,汇集适用于Windows电脑的办公、设计、安全防护、影音播放、开发工具和系统优化软件,提供软件介绍、系统要求、正版授权及购买下载服务。

    PDF教程
    PDF教程

    正软商城PDF教程频道提供PDF编辑、转换、合并、拆分、压缩及格式处理方法,同时介绍常用PDF软件和工具的使用技巧。

    Mac软件 更多
    讯飞智作 网页版
    讯飞智作 网页版
    Windows/ macOS/ Linux

    讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

    火山引擎 网页版
    火山引擎 网页版
    Windows/ macOS/ Linux

    火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

    Aperty macOS版
    Aperty macOS版
    macOS

    Aperty 是 Skylum 推出的 AI 人像修图软件,支持自然肤质修饰、瑕疵处理、面部与身体调整、预设及批量同步。

    WINDOWS 更多
    讯飞智作 网页版
    讯飞智作 网页版
    Windows/ macOS/ Linux

    讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

    火山引擎 网页版
    火山引擎 网页版
    Windows/ macOS/ Linux

    火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

    PixTV 网页版
    PixTV 网页版
    Windows

    PixTV 是一款在浏览器中使用的 AI 视觉内容创作平台,提供图片、视频、音频、文字生成、AI 分镜、局部重绘、提示词反推和无限画布等工具,适合短剧、漫剧、广告及社交媒体内容制作。

    为什么要购买正版软件?
    01 官方授权

    授权来源透明,订单与许可信息可随时查询。

    02 即时交付

    付款成功后自动发放激活信息,支持订单追踪。

    03 中文协助

    安装、激活、迁移与续费问题都有专人响应。

    04 长期可用

    提供升级提醒与授权管理,换机时也能轻松迁移。

    网站备案号:苏ICP备2026018738号-1 联系邮箱:bd@zhengruan.com 网站地图

    Copyright ©2018-2026