java for循环内执行多线程

目录

一、java用多线程来加快循环效率(推荐第3种!!!!)

 第一种:线程池搭配闭锁

 第二种:分页概念执行线程

 第三种:分页概念执行线程进阶版!!!!


一、java用多线程来加快循环效率(推荐第3种!!!!

 第一种:线程池搭配闭锁

涉及知识:Executors(线程池)、CountDownLatch(闭锁)

优点:代码简洁,方便阅读,性能稳定;

缺点:Executors创建的线程池是公用的,如果多个地方使用这种循环多线程的方式,就会抢夺线程池资源,这样运行速度也会降低;

import java.util.*;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class test{

    public static void main(String[] args) throws Exception {

		/**
		 *  两个要点:
		 *  1.用Executors实现固定大小的线程池,从而达到控制硬件资源消耗的目的。
		 *  2.用CountDownLatch(闭锁),来确保循环内的多线程都执行完成后,再执行后续代码
		 */

		// 固定的线程池(当前线程池大小为5
		final ExecutorService executor = Executors.newFixedThreadPool(5);

		// 初始化数据
		List<Map<String,Object>> list = new ArrayList<>();
		for(int i=0;i<50;i++){
			Map<String,Object> object = new HashMap<>();
			object.put("index",i);
			list.add(object);
		}

		// 初始化计时器
		final CountDownLatch cdl = new CountDownLatch(list.size());
		System.out.println("====== 线程开始 =====");

		// 遍历
		for(final Map<String,Object> object:list){
			// 开启线程
			executor.submit(new Runnable() {
				@Override
				public void run() {
					try {
						Thread t = Thread.currentThread();
						String name = t.getName();
						// 模拟运行耗时
						Thread.sleep(500);
						System.out.println(name+":执行到"+object.get("index"));
						object.put("status","已经执行过");
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					// 闭锁-1
					cdl.countDown();
				}
			});
		}

		// 调用闭锁的await()方法,该线程会被挂起,它会等待直到count值为0才继续执行
		// 这样我们就能确保上面多线程都执行完了才走后续代码
		cdl.await();
		

		//关闭线程池
		executor.shutdown();
		System.out.println("====== 线程结束 =====");

		// 校验多线程正确性
		for(Map<String,Object> object:list){
			System.out.println(object.get("index") + ":" + object.get("status"));
		}

	}
}

 第二种:分页概念执行线程

涉及知识:CountDownLatch(闭锁)

优点:运行速度快;

缺点:代码阅读难;

public static void main(String[] args) throws InterruptedException {
		/**
		 *  两个要点:
		 *  1.设定线程数量,用分页的概念,将集合拆分成若干组分批执行线程
		 *  2.用CountDownLatch(闭锁),来确保循环内的多线程都执行完成后,再执行后续代码
		 */

		// 初始化数据
		final List<Map<String,Object>> list = new ArrayList<>();
		for(int i=0;i<6;i++){
			Map<String,Object> object = new HashMap<>();
			object.put("index",i);
			list.add(object);
		}

		int size = list.size(); //集合总数
		int theadCount = 5; // 执行线程数量
		int splitCount = size / theadCount + (size % theadCount != 0 ? 1 : 0); //计算分拆数量,向上取整
		final CountDownLatch cdl = new CountDownLatch(size); //计数器

		for (int i = 1; i <= theadCount; i++) {
			final int beign = (i - 1)  * splitCount;
			final int end = (i * splitCount) > size ? size : i * splitCount;
			if(beign >= end) break;

			new Thread(new Runnable() {
				@Override
				public void run() {
					for (int j = beign; j < end; j++) {
						try {
							Thread t = Thread.currentThread();
							String name = t.getName();
							// 模拟运行耗时
							Thread.sleep(500);
							Map<String, Object> object = list.get(j);
							System.out.println(name+":执行到"+object.get("index"));
							object.put("status","已经执行过");

						} catch (InterruptedException e) {
							e.printStackTrace();
						}
						// 闭锁-1
						cdl.countDown();
					}
				}
			}).start();
		}

		// 调用闭锁的await()方法,该线程会被挂起,它会等待直到count值为0才继续执行
		// 这样我们就能确保上面多线程都执行完了才走后续代码
		cdl.await();
		System.out.println("====== 线程结束 =====");
		// 校验多线程正确性
		for(Map<String,Object> object:list){
			System.out.println(object.get("index") + ":" + object.get("status"));
		}


	}

 第三种:分页概念执行线程进阶版!!!!

涉及知识:CountDownLatch(闭锁)、对象封装;

优点:运行速度快,代码简洁优雅;

缺点:;

package com.xxx;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

/***
 * 多线程优化 by lyx 20230318
 * 在循环里跑多线程,提高执行速度
 */
public class TheadMultis {

    private Integer theadCount; //线程数量

    private Integer size; //集合大小

    private Integer timeOut = 60; //超时时间(单位:分钟)

    private Function function; //执行方法


    public interface Function {
        void run(int i);
    }

    public TheadMultis(int theadCount, int size, Function function) {
        this.theadCount = theadCount;
        this.size = size;
        this.function = function;
    }
    public TheadMultis(int theadCount, int timeOut, int size, Function function) {
        this.theadCount = theadCount;
        this.timeOut = timeOut;
        this.size = size;
        this.function = function;
    }

    public void start() throws InterruptedException,TheadMultisException {
        int size = this.size; //集合总数
        int theadCount = this.theadCount; // 执行线程数量
        int splitCount = size / theadCount + (size % theadCount != 0 ? 1 : 0); //计算分拆数量,向上取整
        final CountDownLatch cdl = new CountDownLatch(size); //计数器

        for (int i = 1; i <= theadCount; i++) {
            final int beign = (i - 1)  * splitCount;
            final int end = (i * splitCount) > size ? size : i * splitCount;
            if(beign >= end) break;

            new Thread(new Runnable() {
                @Override
                public void run() {
                    for (int j = beign; j < end; j++) {
                        try{
                            function.run(j);
                        }catch (Exception e){
                            e.printStackTrace();
                        }
                        // 闭锁-1
                        cdl.countDown();
                    }
                }
            }).start();
        }

        int time = this.timeOut != null ? this.timeOut : 60;
        // 调用闭锁的await()方法,该线程会被挂起,它会等待直到count值为0才继续执行
        // 这样我们就能确保上面多线程都执行完了才走后续代码
        try{
            if(!cdl.await(time, TimeUnit.MINUTES)){
                throw new TheadMultisException("Executed for more than "+ time +" minutes");
            }
        }catch (InterruptedException e){
            throw e;
        }
    }

    public class TheadMultisException extends Exception{

        public TheadMultisException() {
            super();
        }

        public TheadMultisException(String s) {
            super(s);
        }
    }

    public static void main(String[] args) throws Exception {
        // 初始化数据
        final List<Map<String,Object>> list = new ArrayList<>();
        for(int i=0;i<10;i++){
            Map<String,Object> object = new HashMap<>();
            object.put("index",i);
            list.add(object);
        }

        new TheadMultis(2, 1,list.size(), new TheadMultis.Function() {
            @Override
            public void run(int i) {
                Thread t = Thread.currentThread();
                String name = t.getName();
                // 模拟运行耗时
                try {
//                    Thread.sleep(1000 * 60);
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                Map<String, Object> object = list.get(i);
                System.out.println(name+":执行到"+object.get("index"));
                object.put("status","已经执行过");
            }
        }).start();

        System.out.println("====== 线程结束 =====");
        // 校验多线程正确性
        for(Map<String,Object> object:list){
            System.out.println(object.get("index") + ":" + object.get("status"));
        }

    }
}

  • 30
    点赞
  • 173
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值