簡體   English   中英

為什么單線程比Java中的多線程更快?

[英]Why single thread is faster than multithreading in Java?

據我所知,我已經編寫了下面簡單的單線程和多線程程序來檢查執行速度。 但我的單線程程序執行速度比多線程快,請看下面的程序並提及是否有任何錯誤。

單線程:

import java.util.Calendar;

public class NormalJava {
    public static void main(String[] args) {
        System.out.println("Single Thread");
        int a = 1000;
        int b = 200;
        NormalJava nj = new NormalJava();
        nj.Add(a, b);
        nj.Sub(a, b);
        nj.Mul(a, b);
        nj.Div(a, b);
        Calendar lCDateTime = Calendar.getInstance();
        System.out.println("Calender - Time in milliseconds :"
                + lCDateTime.getTimeInMillis());

    }

    private void Add(int a, int b) {
        System.out.println("Add :::" + (a + b));
    }

    private void Sub(int a, int b) {
        System.out.println("Sub :::" + (a - b));
    }

    private void Mul(int a, int b) {
        System.out.println("Mul :::" + (a * b));
    }

    private void Div(int a, int b) {
        System.out.println("Mul :::" + (a / b));
    }
}

輸出:
單線程
添加::: 1200
Sub ::: 800
Mul ::: 200000
Mul ::: 5
日歷 - 以毫秒為單位的時間:138 415 866 7863


多線程程序:

package runnableandcallable;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class MainThread {

    private static ExecutorService service = Executors.newFixedThreadPool(10); // connection
                                                                               // pool
    @SuppressWarnings("unchecked")
    public static void main(String[] args) throws InterruptedException {
        System.out.println("Multithreading");
        MainThread mt = new MainThread();
        mt.testThread(1000, 200);
        Calendar lCDateTime = Calendar.getInstance();
        System.out.println("Calender - Time in milliseconds :"
                + lCDateTime.getTimeInMillis());
    }

    public void testThread(final int a, final int b) {
        // create a callable for each method
        Callable<Void> callableAdd = new Callable<Void>() {
            @Override
            public Void call() throws Exception {
                Add(a, b);
                return null;
            }
        };

        Callable<Void> callableSub = new Callable<Void>() {
            @Override
            public Void call() throws Exception {
                Sub(a, b);
                return null;
            }
        };

        Callable<Void> callableMul = new Callable<Void>() {
            @Override
            public Void call() throws Exception {
                Mul(a, b);
                return null;
            }
        };

        Callable<Void> callableDiv = new Callable<Void>() {
            @Override
            public Void call() throws Exception {
                Div(a, b);
                return null;
            }
        };

        // add to a list
        List<Callable<Void>> taskList = new ArrayList<Callable<Void>>();
        taskList.add(callableAdd);
        taskList.add(callableSub);
        taskList.add(callableMul);
        taskList.add(callableDiv);

        // create a pool executor with 3 threads
        ExecutorService executor = Executors.newFixedThreadPool(3);

        try {
            // start the threads
            List<Future<Void>> futureList = executor.invokeAll(taskList);

            for (Future<Void> voidFuture : futureList) {
                try {
                    // check the status of each future. get will block until the
                    // task
                    // completes or the time expires
                    voidFuture.get(100, TimeUnit.MILLISECONDS);
                } catch (ExecutionException e) {
                    System.err
                            .println("Error executing task " + e.getMessage());
                } catch (TimeoutException e) {
                    System.err.println("Timed out executing task"
                            + e.getMessage());
                }

            }

        } catch (InterruptedException ie) {
            // do something if you care about interruption;
        }

    }

    private void Add(int a, int b) {
        System.out.println("Add :::" + (a + b));
    }

    private void Sub(int a, int b) {
        System.out.println("Sub :::" + (a - b));
    }

    private void Mul(int a, int b) {
        System.out.println("Multiply :::" + (a * b));
    }

    private void Div(int a, int b) {
        System.out.println("Division :::" + (a / b));
    }

}

多線程輸出:
多線程
Sub ::: 800
師::: 5
添加::: 1200
乘以::: 200000
日歷 - 以毫秒為單位的時間:138 415 868 0821

這里單線程執行138 415 866 7863毫秒,多線程執行138 415 868 0821毫秒。 那么多線程的真正目的是什么?

您正在進行的處理非常簡單,因此創建線程的開銷更加昂貴。

如果你有可以並行完成的昂貴操作,那么多線程是有意義的。

第一 :因為創建線程的開銷超過了它們執行的有用工作。如果你在線程中運行更多的工作,它將使它比一個線程更快。必須在一個線程中運行必須的代碼。

第二 :對於創建微基准,你應該使用JMH

1,384,158,667,863毫秒約為44年。 所以你告訴我們你等了44年這次行動的結果? 或者你測量執行速度的方式有問題嗎?

要測量兩次之間的差異,您至少需要兩次,而您只能在程序結束時獲得當前日期,這甚至不准確。

簡單的時間測量類:

public class StopWatch {
  private long startTime = -1;

  public void start() {
    this.startTime = System.nanoTime();
  }

  public long timeNanos() {
    return System.nanoTime() - this.startTime;
  }

  public double timeMillis() {
    return this.timeNanos() / 1000000.0;
  }
}

使用此秒表來測量執行的時間(就像你使用秒表一樣),然后做3次,並意識到每次你得到完全不同的結果。 這是因為測量精確的執行時間根本不是微不足道的。 操作系統不斷地用其他任務中斷程序的執行,看似簡單的命令可以有一整套需要運行的后台命令。

您所能做的就是通過運行該任務一百萬次來估算所需的時間,然后取平均值。

首先,你以毫秒為單位的時間只是時間戳。 您需要在調用之前和之后的毫秒差異,以便測量經過的時間。 我想你先運行單線程應用程序。 如果您嘗試首先運行多線程應用程序,您會注意到它具有較低的“以毫秒為單位的時間”值。

第二。 創建和管理線程會產生開銷,這遠遠高於您執行的非常簡單的算術運算的運行時間。 如果您嘗試將操作迭代幾百萬次,則可能會通過並行執行操作來獲得性能提升。

如果你考慮一台處理器機器。 所有線程都在單個處理器上運行。 假設你的程序(jvm)每秒在處理器上有0.2秒的執行時間。 如果在單個線程上執行,則0.2秒將僅專用於此主線程。 如果你在4個線程上執行它,例如0.2秒,你就不會有0.05 + 0.05 + 0.05 + 0.05。 您將需要額外的時間來同步,恢復和處置線程。 如果我們假設每次上下文切換這個操作需要0.001秒。 如果線程在一秒鍾內執行一次,則每秒會丟失0.004秒的執行時間。 在現實生活中,線程上下文切換每秒進行多次,並且它是不可預測的。 現在情況正在發生變化,因為有多核機器和線程可以在不同的核心上同時執行。

請參閱此鏈接以獲取更多信息: Java是否支持多核處理器/並行處理?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM