17

据我了解,我在下面编写了简单的单线程和多线程程序来检查执行速度。但是我的单线程程序执行速度比多线程快,请看下面的程序并指出是否有任何问题。

单线程:

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

输出:
单线程
Add :::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
Division :::5
Add :::1200
Multiply :::200000
日历 - 时间(以毫秒为单位):138 415 868 0821

这里单线程以 138 415 866 7863 毫秒执行,多线程在这 138 415 868 0821 毫秒执行。那么多线程的真正目的是什么?

4

5 回答 5

38

您正在进行的处理是微不足道的,因此创建线程的开销更昂贵。

如果您有可以并行完成的昂贵操作,那么多线程是有意义的。

于 2013-11-11T08:34:02.450 回答
8

第一:因为创建线程的开销比它们执行的有用工作更多。如果你在线程中运行更多的艰苦工作,它会比一个线程更快。琐碎的代码必须在一个线程中运行。

第二:对于创建微基准,您应该使用JMH

于 2013-11-11T08:35:41.527 回答
6

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 次,并意识到每次得到完全不同的结果。这是因为测量准确的执行时间并非易事。操作系统会不断地用其他任务中断程序的执行,看似简单的命令可能会有一整串需要运行的后台命令。

您所能做的就是通过将任务运行一百万次来估算所需的时间,然后取平均值。

于 2013-11-11T13:08:09.907 回答
4

首先,以毫秒为单位的时间只是时间戳。您需要通话前后的毫秒差来测量经过的时间。我猜您首先运行了单线程应用程序。如果您首先尝试运行多线程应用程序,您会注意到它的“时间(以毫秒为单位)”值较低。

第二。创建和管理线程有开销,这远远高于您执行的非常简单的算术运算的运行时间。如果您尝试将操作迭代几百万次,您可能会看到通过并行执行操作来获得性能提升。

于 2013-11-11T08:39:58.587 回答
2

如果您考虑一台处理器机器。所有线程都在单个处理器上运行。假设您的程序 (jvm) 在处理器上每秒有 0.2 秒的执行时间。如果在单个线程上执行,则 0.2 秒将仅用于此主线程。如果您在 4 个线程上执行它,例如 0.2 秒,您将没有 0.05 + 0.05 + 0.05 + 0.05。您将需要添加额外的时间来同步、恢复和处置线程。如果我们假设这个操作每次上下文切换需要 0.001 秒。如果线程每秒执行一次,您将每秒损失 0.004 秒的执行时间。在现实生活中,线程上下文切换每秒会进行多次,而且是不可预测的。

有关更多信息,请参阅此链接:Java 是否支持多核处理器/并行处理?

于 2014-05-05T09:10:05.323 回答