首頁 > Java > java教程 > java for循環內執行多執行緒問題怎麼解決

java for循環內執行多執行緒問題怎麼解決

WBOY
發布: 2023-04-29 16:55:07
轉載
1885 人瀏覽過

    java用多執行緒來加快循環效率

    執行緒池搭配閉鎖

    #涉及知識:Executors(執行緒池)、CountDownLatch(閉鎖)

    優點:程式碼簡潔,方便閱讀,效能穩定;

    缺點:Executors所建立的執行緒池是公用的,如果多個地方使用這種循環多執行緒的方式,就會搶奪線程池資源,這樣運行速度也會降低;

    import java.util.*;
    import java.util.concurrent.CountDownLatch;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
     
    public class test{
     
        /** 固定的线程池(当前线程池大小为5) */
        private static final ExecutorService executor = Executors.newFixedThreadPool(5);
        
        public static void main(String[] args) throws Exception {
            /**
             *  两个要点:
             *  1.用Executors实现固定大小的线程池,从而达到控制硬件资源消耗的目的。
             *  2.用CountDownLatch(闭锁),来确保循环内的多线程都执行完成后,再执行后续代码
             */
            
            // 初始化数据
            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);
            }
     
            // 初始化计时器
            CountDownLatch cdl = new CountDownLatch(list.size());
            System.out.println("====== 线程开始 =====");
     
            // 遍历
            for(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"));
            }
     
        }
    }
    登入後複製

    for循環中使用多線程

    每個service負責一個業務,多次進行重複業務就要使用到for循環,例如對某個儲存id的集合遍歷,並為每個id創建一些東西。

    但是使用單執行緒執行任務會因為等待上次任務執行完而浪費很多時間,一旦某次執行報錯,任務就會停止執行,明顯不符合我們的要求。

    這種情況就在for迴圈中使用多執行緒。

    import java.util.concurrent.LinkedBlockingQueue;
    import java.util.concurrent.ThreadPoolExecutor;
     
    public class Test {
     
        /**
         * ThreadPool 自定义一个线程池
         */
        private static final ThreadPoolExecutor EXECUTOR = new ThreadPoolExecutor(2, 4, 60L, TimeUnit.SECONDS, new LinkedBlockingQueue<>(60000));
     
        public static void main(String[] args) {
            //自己的数组或集合,这里不再进行填充
            String[] ids = new String[10]
            
            for (String id : ids) {
                EXECUTOR.execute(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            //需要执行的业务逻辑
                            System.out.println("业务逻辑正在执行");
                        } catch (Exception e) {
                            //todo
                        }
                    }
                });
            }
        }
     
    }
    登入後複製

    以上是java for循環內執行多執行緒問題怎麼解決的詳細內容。更多資訊請關注PHP中文網其他相關文章!

    相關標籤:
    來源:yisu.com
    本網站聲明
    本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
    熱門教學
    更多>
    最新下載
    更多>
    網站特效
    網站源碼
    網站素材
    前端模板