Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/joomla/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 除非线程的run()方法中放入了Thread.sleep(1),否则超过2个线程的运行速度比1或2个线程慢_Java_Multithreading_Threadpool_Executorservice_Collatz - Fatal编程技术网

Java 除非线程的run()方法中放入了Thread.sleep(1),否则超过2个线程的运行速度比1或2个线程慢

Java 除非线程的run()方法中放入了Thread.sleep(1),否则超过2个线程的运行速度比1或2个线程慢,java,multithreading,threadpool,executorservice,collatz,Java,Multithreading,Threadpool,Executorservice,Collatz,我试图实现的任务是使用多个线程在设定的时间间隔内查找数字的Collatz序列,并查看与一个线程相比有多少改进 然而,无论我选择2个线程,一个线程总是更快(编辑。2个线程更快,但不多,而4个线程比1个线程慢,我不知道为什么。(我甚至可以说线程越多,速度越慢)。我希望有人能解释。也许我做错了什么 下面是我到目前为止编写的代码。我使用ThreadPoolExecutor执行任务(一个任务=间隔中一个数字的一个Collatz序列) Collatz类: public class ParallelC

我试图实现的任务是使用多个线程在设定的时间间隔内查找数字的Collatz序列,并查看与一个线程相比有多少改进

然而,无论我选择2个线程,一个线程总是更快(编辑。2个线程更快,但不多,而4个线程比1个线程慢,我不知道为什么。(我甚至可以说线程越多,速度越慢)。我希望有人能解释。也许我做错了什么

下面是我到目前为止编写的代码。我使用ThreadPoolExecutor执行任务(一个任务=间隔中一个数字的一个Collatz序列)

Collatz类:

    public class ParallelCollatz implements Runnable {
    private long result;
    private long inputNum;

    public long getResult() {
        return result;
    }
    public void setResult(long result) {
        this.result = result;
    }
    public long getInputNum() {
        return inputNum;
    }
    public void setInputNum(long inputNum) {
        this.inputNum = inputNum;
    }
    public void run() {

        //System.out.println("number:" + inputNum);
        //System.out.println("Thread:" + Thread.currentThread().getId());
        //int j=0;
        //if(Thread.currentThread().getId()==11) {
        //  ++j;
        //  System.out.println(j);
        //}

            long result = 1;

            //main recursive computation
            while (inputNum > 1) {

                if (inputNum % 2 == 0) {
                    inputNum = inputNum / 2;
                } else {
                    inputNum = inputNum * 3 + 1;
                }
                ++result;
            }
           // try {
                //Thread.sleep(10);
            //} catch (InterruptedException e) {
                // TODO Auto-generated catch block
        //      e.printStackTrace();
            //}
            this.result=result;
            return;
        }

}
以及我运行线程的主类(是的,现在我创建了两个具有相同编号的列表,因为在运行一个线程后,初始值丢失):

ThreadPoolExecutor executor=(ThreadPoolExecutor)Executors.newFixedThreadPool(1);
ThreadPoolExecutor Executor 2=(ThreadPoolExecutor)Executors.newFixedThreadPool(4);
列表任务=新建ArrayList();

对于(int i=1;i您不是在等待任务完成,而是在测量将任务提交给执行者所需的时间

executor.shutdown()
不会等待所有任务完成。之后需要调用
executor.waitTermination

executor.shutdown();
executor.awaitTermination(5, TimeUnit.HOURS);

更新 我相信我们的测试方法是有缺陷的。我在我的机器上重复了你的测试,(1个处理器,2个内核,4个逻辑处理器),每次运行的时间差别很大

我相信主要原因如下:

  • JVM启动和JIT编译时间。开始时,代码以解释模式运行
  • 计算结果被忽略了。我没有直觉,JIT删除了什么,我们实际测量的是什么
  • 代码中的打印行
为了测试这一点,我将您的测试转换为JMH。 特别是:

  • 我将runnable转换为callable,并返回结果的总和以防止内联(或者,您可以使用JMH中的BlackHole)
  • 我的任务没有状态,我将所有移动部件移动到局部变量。清理任务不需要GC
  • 我仍然在每一轮中创建执行者。这并不完美,但我决定保持原样
我在下面收到的结果与我的预期一致:一个内核在主线程中等待,工作在单个内核上执行,数量几乎相同

Benchmark                  Mode  Cnt    Score    Error  Units
SpeedTest.multipleThreads  avgt   20  559.996 ± 20.181  ms/op
SpeedTest.singleThread     avgt   20  562.048 ± 16.418  ms/op
更新代码:

public class ParallelCollatz implements Callable<Long> {

    private final long inputNumInit;

    public ParallelCollatz(long inputNumInit) {
        this.inputNumInit = inputNumInit;
    }


    @Override
    public Long call() {
        long result = 1;
        long inputNum = inputNumInit;
        //main recursive computation
        while (inputNum > 1) {

            if (inputNum % 2 == 0) {
                inputNum = inputNum / 2;
            } else {
                inputNum = inputNum * 3 + 1;
            }
            ++result;
        }
        return result;
    }

}
公共类ParallelCollatz实现了可调用{
私人最终长输入;
公共并行Collatz(长输入){
this.inputNumInit=inputNumInit;
}
@凌驾
公共长途电话(){
长期结果=1;
长inputNum=inputnumini;
//主递归计算
while(inputNum>1){
如果(inputNum%2==0){
inputNum=inputNum/2;
}否则{
inputNum=inputNum*3+1;
}
++结果;
}
返回结果;
}
}
以及基准本身:

@State(Scope.Benchmark)
public class SpeedTest {
private static final int NUM_TASKS = 1000000;

    private static List<ParallelCollatz> tasks = buildTasks();

    @Benchmark
    @Fork(value = 1, warmups = 1)
    @BenchmarkMode(Mode.AverageTime)
    @OutputTimeUnit(TimeUnit.MILLISECONDS)
    @SuppressWarnings("unused")
    public long singleThread() throws Exception {
        ThreadPoolExecutor executorOneThread = (ThreadPoolExecutor) Executors.newFixedThreadPool(1);
        return measureTasks(executorOneThread, tasks);
    }

    @Benchmark
    @Fork(value = 1, warmups = 1)
    @BenchmarkMode(Mode.AverageTime)
    @OutputTimeUnit(TimeUnit.MILLISECONDS)
    @SuppressWarnings("unused")
    public long multipleThreads() throws Exception {
        ThreadPoolExecutor executorMultipleThread = (ThreadPoolExecutor) Executors.newFixedThreadPool(4);
        return measureTasks(executorMultipleThread, tasks);
    }

    private static long measureTasks(ThreadPoolExecutor executor, List<ParallelCollatz> tasks) throws InterruptedException, ExecutionException {
        long sum = runTasksInExecutor(executor, tasks);
       return sum;
    }

    private static long runTasksInExecutor(ThreadPoolExecutor executor, List<ParallelCollatz> tasks) throws InterruptedException, ExecutionException {
        List<Future<Long>> futures = new ArrayList<>(NUM_TASKS);
        for (int i = 0; i < NUM_TASKS; i++) {
            Future<Long> f = executor.submit(tasks.get(i));
            futures.add(f);
        }
        executor.shutdown();

        boolean tempFirst = false;
        try {
            tempFirst = executor.awaitTermination(5, TimeUnit.HOURS);
        } catch (InterruptedException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }
        long sum = 0l;
        for (Future<Long> f : futures) {
            sum += f.get();
        }
        //System.out.println(sum);
        return sum;
    }

    private static List<ParallelCollatz> buildTasks() {
        List<ParallelCollatz> tasks = new ArrayList<>();
        for (int i = 1; i <= NUM_TASKS; i++) {
            ParallelCollatz task = new ParallelCollatz((long) (i + NUM_TASKS));

            tasks.add(task);

        }
        return tasks;
    }

}
@State(Scope.Benchmark)
公开课速考{
私有静态最终int NUM_任务=1000000;
私有静态列表任务=buildTasks();
@基准
@叉(值=1,预热=1)
@基准模式(模式平均时间)
@OutputTimeUnit(时间单位毫秒)
@抑制警告(“未使用”)
公共长单线程()引发异常{
ThreadPoolExecutor executorOneThread=(ThreadPoolExecutor)Executors.newFixedThreadPool(1);
返回度量任务(executorOneThread,tasks);
}
@基准
@叉子(值=1,预热=1)
@基准模式(模式平均时间)
@OutputTimeUnit(时间单位毫秒)
@抑制警告(“未使用”)
public long multipleThreads()引发异常{
ThreadPoolExecutor Executor MultipleThread=(ThreadPoolExecutor)Executors.newFixedThreadPool(4);
返回度量任务(executorMultipleThread,任务);
}
私有静态长度量任务(ThreadPoolExecutor executor,List tasks)引发InterruptedException,ExecutionException{
长和=运行任务执行器(执行器,任务);
回报金额;
}
私有静态长时间运行任务执行器(ThreadPoolExecutor,executor,List tasks)引发InterruptedException,ExecutionException{
列表未来=新数组列表(NUM_任务);
对于(int i=0;i对于(int i=1;i您不是在等待任务完成,而是在测量将任务提交给执行者所需的时间

executor.shutdown()
不会等待所有任务完成。之后需要调用
executor.waitTermination

executor.shutdown();
executor.awaitTermination(5, TimeUnit.HOURS);

更新 我相信我们的测试方法是有缺陷的。我在我的机器上重复了你的测试,(1个处理器,2个内核,4个逻辑处理器),每次运行的时间差别很大

我相信主要原因如下:

  • JVM启动和JIT编译时间。开始时,代码以解释模式运行
  • 计算的结果被忽略了。我没有直觉什么