使用多線程處理任務會快嗎

剛開始接觸java的時候免不了對多線程技術總是懷抱着好奇心,總想弄明白多線程好在哪裏。甚至於認爲使用多線程效率就比單線程要高。但事實真的如此嗎?下面我們做一些測試

測試1-單線程執行效率

public static void main(String[] args) {
        Long start = System.currentTimeMillis();

        // 總數據條數
        int dataSize = 5000;

        System.out.println("開啓1個線程...");

        // 創建一個線程池
        ExecutorService pool = new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>());

        for (int i = 0; i <dataSize ; i++) {
            //放到線程池中,線程異步執行
            pool.execute(new Thread() {
                @Override
                public void run() {
                    try {
                        //模擬業務處理數據的時間
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });
        }
        //當調用shutdown()方法後,並且所有提交的任務完成後,isTerminated()返回爲true;
        pool.shutdown();

        while (true) {
            if (pool.isTerminated()) {//所有的子線程都結束了
                break;
            }
        }

        Long end = System.currentTimeMillis();

        System.out.println("總共花費了===========" + (end - start) / 1000 + "." + (end - start) % 1000 + "s");
    }

結果:
在這裏插入圖片描述

測試2-多線程執行效率(5個線程異步執行)

public static void main(String[] args) {

        Long start = System.currentTimeMillis();

        // 總數據條數
        int dataSize = 5000;

        // 每1000條數據開啓一條線程
        int threadSize = 1000;

        // 線程數
        int threadNum = dataSize / threadSize;

        System.out.println("開啓" + threadNum + "個線程...");

        ExecutorService pool = new ThreadPoolExecutor(threadNum, threadNum, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>());

        // 分割成多個線程執行
        for (int i = 0; i < dataSize; i++) {
            //放到線程池中,線程異步執行
            pool.execute(new Thread() {
                @Override
                public void run() {
                    try {
                        //模擬業務處理數據的時間
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });
        }

        pool.shutdown();

        while (true) {
            if (pool.isTerminated()) {
                break;
            }
        }

        Long end = System.currentTimeMillis();

        System.out.println("總共花費了===========" + (end - start) / 1000 + "." + (end - start) % 1000 + "s");
    }

結果:
在這裏插入圖片描述

測試3-多線程執行效率(50個線程異步執行)

public static void main(String[] args) {

        Long start = System.currentTimeMillis();

        // 總數據條數
        int dataSize = 5000;

        // 每100條數據開啓一條線程
        int threadSize = 100;

        // 線程數
        int threadNum = dataSize / threadSize;

        System.out.println("開啓" + threadNum + "個線程...");

        ExecutorService pool = new ThreadPoolExecutor(threadNum, threadNum, 0L, TimeUnit.SECONDS, new LinkedBlockingQueue<>());

        // 分割成多個線程執行
        for (int i = 0; i < dataSize; i++) {
            //放到線程池中,線程異步執行
            pool.execute(new Thread() {
                @Override
                public void run() {
                    try {
                        //模擬業務處理數據的時間
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });
        }

        pool.shutdown();

        while (true) {
            if (pool.isTerminated()) {
                break;
            }
        }

        Long end = System.currentTimeMillis();

        System.out.println("總共花費了===========" + (end - start) / 1000 + "." + (end - start) % 1000 + "s");
    }

結果:
在這裏插入圖片描述

測試4-多線程執行效率(500個線程異步執行)

public static void main(String[] args) {

        Long start = System.currentTimeMillis();

        // 總數據條數
        int dataSize = 5000;

        // 每10條數據開啓一條線程
        int threadSize = 10;

        // 線程數
        int threadNum = dataSize / threadSize;

        System.out.println("開啓" + threadNum + "個線程...");

        ExecutorService pool = new ThreadPoolExecutor(threadNum, threadNum, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>());

        // 分割成多個線程執行
        for (int i = 0; i < dataSize; i++) {
            //放到線程池中,線程異步執行
            pool.execute(new Thread() {
                @Override
                public void run() {
                    try {
                        //模擬業務處理數據的時間
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });
        }

        pool.shutdown();

        while (true) {
            if (pool.isTerminated()) {
                break;
            }
        }

        Long end = System.currentTimeMillis();

        System.out.println("總共花費了===========" + (end - start) / 1000 + "." + (end - start) % 1000 + "s");
    }

結果:
在這裏插入圖片描述

測試5-多線程執行效率(1000個線程異步執行)

public static void main(String[] args) {

        Long start = System.currentTimeMillis();

        // 總數據條數
        int dataSize = 5000;

        // 每5條數據開啓一條線程
        int threadSize = 5;

        // 線程數
        int threadNum = dataSize / threadSize;

        System.out.println("開啓" + threadNum + "個線程...");

        ExecutorService pool = new ThreadPoolExecutor(threadNum, threadNum, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>());

        // 分割成多個線程執行
        for (int i = 0; i < threadNum; i++) {
            //放到線程池中,線程異步執行
            pool.execute(new Thread() {
                @Override
                public void run() {
                    try {
                        //模擬業務處理數據的時間
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });
        }

        pool.shutdown();

        while (true) {
            if (pool.isTerminated()) {
                break;
            }
        }

        Long end = System.currentTimeMillis();

        System.out.println("總共花費了===========" + (end - start) / 1000 + "." + (end - start) % 1000 + "s");
    }

結果:
在這裏插入圖片描述

測試6-多線程執行效率(5000個線程異步執行)

public static void main(String[] args) {

        Long start = System.currentTimeMillis();

        // 總數據條數
        int dataSize = 5000;

        // 每1條數據開啓一條線程
        int threadSize = 1;

        // 線程數
        int threadNum = dataSize / threadSize;

        System.out.println("開啓" + threadNum + "個線程...");

        ExecutorService pool = new ThreadPoolExecutor(threadNum, threadNum, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>());

        // 分割成多個線程執行
        for (int i = 0; i < threadNum; i++) {
            //放到線程池中,線程異步執行
            pool.execute(new Thread() {
                @Override
                public void run() {
                    try {
                        //模擬業務處理數據的時間
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });
        }

        pool.shutdown();

        while (true) {
            if (pool.isTerminated()) {
                break;
            }
        }

        Long end = System.currentTimeMillis();

        System.out.println("總共花費了===========" + (end - start) / 1000 + "." + (end - start) % 1000 + "s");
    }

結果:
在這裏插入圖片描述

數據分析

1個線程---------------54.554s
5個線程---------------10.947s
50個線程--------------1.139s
500個線程-------------0.182s
1000個線程-----------0.158s
5000個線程-----------0.579s

總結:
多線程的確可以提高併發任務處理效率,特別是初期線程數慢慢提高的時候。但隨着線程數大幅的提高效率卻降低了。在我本地測試的線程數到達5000個的時候明顯效率還不如500個~。這是因爲每臺計算機都有其性能瓶頸,開多少線程效率最高, 和線程的任務利用何種部件,以及這些部件的獨立/共享狀態相關。至於能運行多少個線程與你運行的程序有關,你可以用以下代碼在自己電腦上測試可以開到多少個線程(謹慎使用)。

private static Object object = new Object();
    private static int count = 0;

    public static void main(String[] args) {
        for(;;){
            new Thread(new Runnable(){
                public void run(){
                    synchronized(object){
                        count += 1;
                        System.err.println("New thread #"+count);
                    }
                    for(;;){
                        try {
                            Thread.sleep(1000);
                        } catch (Exception e){
                            System.err.println(e);
                        }
                    }
                }
            }).start();
        }
    }

我用jdk1.8 + windows10 + 4核CPU + 8G內存 最多到 172020 的時候就死機了~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章