简体   繁体   English

为什么单线程比Java中的多线程更快?

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

As of my understanding I have written the simple single and multithreading program below to check the execution speed. 据我所知,我已经编写了下面简单的单线程和多线程程序来检查执行速度。 But my single-threaded program executing faster than multithreaded, kindly see the below program and mention if anything is wrong. 但我的单线程程序执行速度比多线程快,请看下面的程序并提及是否有任何错误。

Single Thread: 单线程:

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));
    }
}

Output: 输出:
Single Thread 单线程
Add :::1200 添加::: 1200
Sub :::800 Sub ::: 800
Mul :::200000 Mul ::: 200000
Mul :::5 Mul ::: 5
Calender - Time in milliseconds :138 415 866 7863 日历 - 以毫秒为单位的时间:138 415 866 7863


Multithreaded Program: 多线程程序:

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));
    }

}

Mulithreading Output: 多线程输出:
Multithreading 多线程
Sub :::800 Sub ::: 800
Division :::5 师::: 5
Add :::1200 添加::: 1200
Multiply :::200000 乘以::: 200000
Calender - Time in milliseconds :138 415 868 0821 日历 - 以毫秒为单位的时间:138 415 868 0821

Here single thread executed at 138 415 866 7863 milliseconds and multithreading executed at this 138 415 868 0821 milliseconds. 这里单线程执行138 415 866 7863毫秒,多线程执行138 415 868 0821毫秒。 Then what is the real purpose of multithreading ? 那么多线程的真正目的是什么?

The processing that you are doing is trivial, so the overhead of creating threads is more expensive. 您正在进行的处理非常简单,因此创建线程的开销更加昂贵。

If you had expensive operations which could be done in parallel then multi threads make sense. 如果你有可以并行完成的昂贵操作,那么多线程是有意义的。

First : Because the overhead of creating threads more, than the useful work performed by them.If you run more hard work in threads, it will make it faster than one thread.Trivial code must be runned in one thread. 第一 :因为创建线程的开销超过了它们执行的有用工作。如果你在线程中运行更多的工作,它将使它比一个线程更快。必须在一个线程中运行必须的代码。

Second : For creation micro-benchmark you should use JMH 第二 :对于创建微基准,你应该使用JMH

1,384,158,667,863 milliseconds are about 44 years. 1,384,158,667,863毫秒约为44年。 So you are telling us that you waited 44 years on the result of this operation? 所以你告诉我们你等了44年这次行动的结果? Or could there be something wrong with the way you are measuring the speed of the execution? 或者你测量执行速度的方式有问题吗?

To measure the difference between two times you need at least two times, while you only get the current date at the end of your program, which isn't even close to accurate. 要测量两次之间的差异,您至少需要两次,而您只能在程序结束时获得当前日期,这甚至不准确。

Simple time measuring class: 简单的时间测量类:

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;
  }
}

Use this Stopwatch to measure the time for execution (like you would use a stopwatch), then do it 3 times and realize that each time you get entirely different results. 使用此秒表来测量执行的时间(就像你使用秒表一样),然后做3次,并意识到每次你得到完全不同的结果。 This is because measuring exact execution time is not trivial at all. 这是因为测量精确的执行时间根本不是微不足道的。 The OS constantly interrupts the execution of your program with other tasks and seemingly easy commands can have a whole chain of background commands that need to be run. 操作系统不断地用其他任务中断程序的执行,看似简单的命令可以有一整套需要运行的后台命令。

All you can do is to approximate the time it takes by running that task like a million times and then take the average. 您所能做的就是通过运行该任务一百万次来估算所需的时间,然后取平均值。

First of all, your time in miliseconds is just the timestamp. 首先,你以毫秒为单位的时间只是时间戳。 You need the difference in miliseconds between before and after the call in order to measure the elapsed time. 您需要在调用之前和之后的毫秒差异,以便测量经过的时间。 I guess that you ran the single-threaded application first. 我想你先运行单线程应用程序。 If you try running the multi-threaded application first, you will notice that it has a lower "time in milliseconds"-value. 如果您尝试首先运行多线程应用程序,您会注意到它具有较低的“以毫秒为单位的时间”值。

Second. 第二。 Creating and managing threads has an overhead, which is far higher than the running time of the very simple arithmetic operations you perform. 创建和管理线程会产生开销,这远远高于您执行的非常简单的算术运算的运行时间。 If you try to iterate the operations a few million times, you may see a performance gain by executing the operations in parallel. 如果您尝试将操作迭代几百万次,则可能会通过并行执行操作来获得性能提升。

If you consider one processor machine. 如果你考虑一台处理器机器。 All the threads run on a single processor. 所有线程都在单个处理器上运行。 let's suppose that your program (jvm) has 0.2 secs execution time on the processor every second. 假设你的程序(jvm)每秒在处理器上有0.2秒的执行时间。 If you execute on a single thread, the 0.2 seconds will be dedicated only to this main thread. 如果在单个线程上执行,则0.2秒将仅专用于此主线程。 If you execute it on 4 threads for example the 0.2 seconds you will not have 0.05 + 0.05 + 0.05 + 0.05. 如果你在4个线程上执行它,例如0.2秒,你就不会有0.05 + 0.05 + 0.05 + 0.05。 You will need to add an extra time to synchronize, resume and dispose threads. 您将需要额外的时间来同步,恢复和处置线程。 If we suppose that this operation takes 0.001 seconds for every context switching. 如果我们假设每次上下文切换这个操作需要0.001秒。 You will get 0.004 seconds of execution time lost every second provided that a thread executes once in a second. 如果线程在一秒钟内执行一次,则每秒会丢失0.004秒的执行时间。 In real life thread context switching is made many times every second and it's unpredictable. 在现实生活中,线程上下文切换每秒进行多次,并且它是不可预测的。 Now things are changing as there are multicore machines and threads can execute at the same time on different cores. 现在情况正在发生变化,因为有多核机器和线程可以在不同的核心上同时执行。

Please see this link for more information: Does Java have support for multicore processors/parallel processing? 请参阅此链接以获取更多信息: Java是否支持多核处理器/并行处理?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM