• 【Java】+多线程 [有返回值]+等待创建的线程 中的 所有线程都结束(再开始执行主线程)


    一、需要多线程执行的任务

    package thread;
    
    import java.text.SimpleDateFormat;
    import java.util.ArrayList;
    import java.util.Date;
    
    /**
     * @Author: 
     * @Date: 2022/3/23 10:53
     * @Description:
     * @Version: v1.0
     */
    public class Job {
        /**
         * 要让线程执行的任务
         *
         * @param returnDataList 用来保存线程执行任务中需要返回数据的对象(线程要返回什么数据 就往这个对象里塞值就行了)
         * @param count          任务的参数
         */
        public void print(ArrayList<ReturnData> returnDataList, String count) {
            String data = String.format("[%s][%s]%s",
                    Thread.currentThread().getName(),
                    count,
                    new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSSS").format(new Date())
            );
            System.out.println(data);
    
            // 在任务中把要返回的数据添加到returnData对象中
            ReturnData returnData = new ReturnData();
            returnData.thread = Thread.currentThread();
            returnData.data = data;
            returnDataList.add(returnData);
        }
    }

    二、多线程工具封装

    备注:可直接调用此封装(仅修改setup1CreateThread方法中对应位置即可)

    功能:有线程返回值;等待创建的线程 中的 所有线程都结束(再开始执行主线程)

    package thread;
    
    import lombok.Data;
    
    import java.util.ArrayList;
    import java.util.HashSet;
    
    /**
     * @Author: 
     * @Date: 2022/3/22 16:12
     * @Description:
     * @Version: v1.0
     */
    
    @Data
    public class MyThread {
        public ArrayList<Thread> threads;
    
        // 用来保存线程执行任务中需要返回数据的对象(线程要返回什么数据 就往这个对象里塞值就行了)
        public ArrayList<ReturnData> returnDataList;
    
        public MyThread() {
            this.threads = new ArrayList<>();
            this.returnDataList = new ArrayList<>();
        }
    
    
        /**
         * 创建线程并给线程添加任务
         * 备注:
         * 1、此方法仅需把 new Job().print(returnDataList, taskParam) 替换为待执行的任务方法即可
         * 2、taskParam 随任务的参数而定
         *
         * @param threadCount 要创建的线程数量
         * @param taskParam   任务的参数
         * @return
         */
        public MyThread setup1CreateThread(int threadCount, String taskParam) {
            for (int i = 0; i < threadCount; i++) {
                // new Job().print(returnDataList, taskParam) 为线程要执行的任务
                Thread th = new Thread(() -> new Job().print(returnDataList, taskParam));
                // 设置线程名称
                th.setName(String.format("MyThread-%s", i + 1));
                threads.add(th);
            }
            return this;
        }
    
        /**
         * 批量启动所有线程
         * 备注:此方法不用修改
         *
         * @return
         */
        public MyThread setup2Starts() {
            for (Thread thread : threads) {
                thread.start();
            }
            return this;
        }
    
        /**
         * 等待threads中的所有线程都结束(再开始执行主线程)
         * 备注:此方法不用修改
         *
         * @return
         */
        public MyThread setup3WaitThreadEnd() {
            while (true) {
                ArrayList<String> thStates = new ArrayList<>();
                for (Thread thread : threads) {
                    thStates.add(thread.getState().name());
                }
                // 第一个线程的状态为终止状态 && 所有线程的状态去重后数量为1(表示所有的线程状态都相同)
                if (threads.get(0).getState().name().equals("TERMINATED") && new HashSet<Object>(thStates).size() == 1) {
                    break;
                }
            }
            return this;
        }
    
    
        public static void main(String[] args) {
            MyThread myThread = new MyThread()
                    // 1 创建线程并给线程添加任务(此时线程还未执行)
                    .setup1CreateThread(10, "这是任务的参数")
                    // 2 批量启动所有线程
                    .setup2Starts()
                    // 3 等待创建的线程 中的 所有线程都结束(再开始执行主线程)
                    .setup3WaitThreadEnd();
    
            System.out.println("创建的所有线程执行完后 才会执行此行");
    
            for (ReturnData returnData : myThread.returnDataList) {
                System.out.println(String.format("线程执行任务的返回数据:%s %s", returnData.thread.getName(), returnData.data));
            }
        }
    }

    三、保存返回数据的对象

    package thread;
    
    import lombok.Data;
    
    /**
     * @Author: 
     * @Date: 2022/3/23 13:49
     * @Description: 用来保存线程执行任务中需要返回数据的对象(线程要返回什么数据 就往这个对象里塞值就行了)
     * @Version: v1.0
     */
    
    @Data
    public class ReturnData {
        /**
         * 线程
         */
        public Thread thread;
    
        /**
         * 当前线程执行任务所保存的数据
         */
        public Object data;
    }

    四、效果

    [MyThread-5][这是任务的参数]2022-03-23 14:15:48.00699
    [MyThread-2][这是任务的参数]2022-03-23 14:15:48.00699
    [MyThread-1][这是任务的参数]2022-03-23 14:15:48.00701
    [MyThread-6][这是任务的参数]2022-03-23 14:15:48.00702
    [MyThread-7][这是任务的参数]2022-03-23 14:15:48.00707
    [MyThread-3][这是任务的参数]2022-03-23 14:15:48.00710
    [MyThread-4][这是任务的参数]2022-03-23 14:15:48.00710
    [MyThread-8][这是任务的参数]2022-03-23 14:15:48.00711
    [MyThread-9][这是任务的参数]2022-03-23 14:15:48.00712
    [MyThread-10][这是任务的参数]2022-03-23 14:15:48.00713
    创建的所有线程执行完后 才会执行此行
    线程执行任务的返回数据:MyThread-5 [MyThread-5][这是任务的参数]2022-03-23 14:15:48.00699
    线程执行任务的返回数据:MyThread-2 [MyThread-2][这是任务的参数]2022-03-23 14:15:48.00699
    线程执行任务的返回数据:MyThread-1 [MyThread-1][这是任务的参数]2022-03-23 14:15:48.00701
    线程执行任务的返回数据:MyThread-6 [MyThread-6][这是任务的参数]2022-03-23 14:15:48.00702
    线程执行任务的返回数据:MyThread-7 [MyThread-7][这是任务的参数]2022-03-23 14:15:48.00707
    线程执行任务的返回数据:MyThread-3 [MyThread-3][这是任务的参数]2022-03-23 14:15:48.00710
    线程执行任务的返回数据:MyThread-4 [MyThread-4][这是任务的参数]2022-03-23 14:15:48.00710
    线程执行任务的返回数据:MyThread-8 [MyThread-8][这是任务的参数]2022-03-23 14:15:48.00711
    线程执行任务的返回数据:MyThread-9 [MyThread-9][这是任务的参数]2022-03-23 14:15:48.00712
    线程执行任务的返回数据:MyThread-10 [MyThread-10][这是任务的参数]2022-03-23 14:15:48.00713
  • 相关阅读:
    C++ 4种强制类型转换
    HTTP与HTTPS异同/HTTP1.0与HTTP1.1差别
    大数据处理-Trie树
    Linux进程状态转换图
    纯css实现背景图片半透明内容不透明的方法-opacity属性正确使用
    由vue理解passive修饰符引起的思考
    Vue+VSCode开发环境配置备忘(代码格式设置)
    哎呦喂web 前端三日老师 《精通Flex布局》
    flex实战之移动页面确定按钮置底布局
    Poptip插件拖动造成IOS下与同页面下mescroll.js也被拖动的解决,即对e.preventDefault();的理解
  • 原文地址:https://www.cnblogs.com/danhuai/p/16044223.html
Copyright © 2020-2023  润新知