当前位置: 首页 > 面试题库 >

服务时间与线程数成正比

邢小云
2023-03-14
问题内容

我的系统是具有超线程的i5-Dual核心。Windows向我显示4个处理器。当我一次通过单个线程运行单个优化的CPU绑定任务时,其服务时间始终显示为大约35ms。但是,当我同时将2个任务移交给2个线程时,它们的服务时间显示为大约70ms。我想问一下我的系统有4个处理器,那么如果2个线程运行teir任务时服务时间为什么会在70左右,而2个线程应该在2个处理器上运行而没有任何调度开销呢?代码如下。

CPU限制任务如下。

import java.math.BigInteger;

html" target="_blank">public class CpuBoundJob  implements Runnable {

    public void run() {

         BigInteger factValue = BigInteger.ONE;
            long t1=System.nanoTime();

            for ( int i = 2; i <= 2000; i++){
              factValue = factValue.multiply(BigInteger.valueOf(i));
            }
        long t2=System.nanoTime();

        System.out.println("Service Time(ms)="+((double)(t2-t1)/1000000));
    }

}

运行任务的线程如下。

public class TaskRunner extends Thread {
    CpuBoundJob job=new CpuBoundJob();
    public void run(){

        job.run();
    }
}

最后,主类如下。

public class Test2 {
int numberOfThreads=100;//warmup code for JIT
public Test2(){
    for(int i=1;i<=numberOfThreads;i++){//warmup code for JIT
        TaskRunner t=new TaskRunner();
        t.start();
        }
    try{
    Thread.sleep(5000);// wait a little bit
    }catch(Exception e){}
    System.out.println("Warmed up completed! now start benchmarking");
    System.out.println("First run single thread at a time");

    try{//wait for the thread to complete
        Thread.sleep(5000);
        }catch(Exception e){}
        //run only one thread at a time
            TaskRunner t1=new TaskRunner();
            t1.start();


    try{//wait for the thread to complete
        Thread.sleep(5000);
        }catch(Exception e){}

    //Now run 2 threads simultanously at a time

    System.out.println("Now run 3 thread at a time");


        for(int i=1;i<=3;i++){//run 2 thread at a time
            TaskRunner t2=new TaskRunner();
            t2.start();


            }


}
public static void main(String[] args) {
    new Test2();    
    }

最终输出:

热身完成!现在开始进行基准测试一次一次运行单线程服务时间(ms)= 5.829112现在一次运行2个线程服务时间(ms)=
6.518721服务时间(ms)= 10.364269服务时间(ms)= 10.272689


问题答案:

我在各种情况下都设置了时间,并且对任务进行了稍微修改,一个线程的时间约为45毫秒,两个线程的时间约为60毫秒。因此,即使在此示例中,一个线程也可以在一秒钟内完成大约22个任务,但是两个线程可以完成33个任务。

但是,如果您执行的任务不会给垃圾收集器带来如此巨大的负担,那么您应该会看到预期的性能提升:两个线程完成的任务数量是原来的两倍。这是我的测试程序版本。

请注意,我对您的任务(DirtyTask)进行了一项重大更改:n始终为0,因为您将结果转换Math.random()为的值int(为零),
然后 乘以13。

然后,我添加了一个CleanTask不会为垃圾收集器处理的新对象的对象。请在您的计算机上测试并报告结果。在我的身上,我得到了这个:

测试“干净”任务。
平均任务时间:一个线程= 46毫秒;两个线程= 45毫秒
测试“脏”任务。
平均任务时间:一个线程= 41毫秒;两个线程= 62毫秒



import java.util.ArrayList;
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.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;

final class Parallels
{

  private static final int RUNS = 10;

  public static void main(String... argv)
    throws Exception
  {
    System.out.println("Testing \"clean\" task.");
    flavor(CleanTask::new);
    System.out.println("Testing \"dirty\" task.");
    flavor(DirtyTask::new);
  }

  private static void flavor(Supplier<Callable<Long>> tasks)
    throws InterruptedException, ExecutionException
  {
    ExecutorService warmup = Executors.newFixedThreadPool(100);
    for (int i = 0; i < 100; ++i)
      warmup.submit(tasks.get());
    warmup.shutdown();
    warmup.awaitTermination(1, TimeUnit.DAYS);
    ExecutorService workers = Executors.newFixedThreadPool(2);
    long t1 = test(1, tasks, workers);
    long t2 = test(2, tasks, workers);
    System.out.printf("Average task time: one thread = %d ms; two threads = %d ms%n", t1 / (1 * RUNS), t2 / (2 * RUNS));
    workers.shutdown();
  }

  private static long test(int n, Supplier<Callable<Long>> tasks, ExecutorService workers)
    throws InterruptedException, ExecutionException
  {
    long sum = 0;
    for (int i = 0; i < RUNS; ++i) {
      List<Callable<Long>> batch = new ArrayList<>(n);
      for (int t = 0; t < n; ++t)
        batch.add(tasks.get());
      List<Future<Long>> times = workers.invokeAll(batch);
      for (Future<Long> f : times)
        sum += f.get();
    }
    return TimeUnit.NANOSECONDS.toMillis(sum);
  }

  /**
   * Do something on the CPU without creating any garbage, and return the 
   * elapsed time.
   */
  private static class CleanTask
    implements Callable<Long>
  {
    @Override
    public Long call()
    {
      long time = System.nanoTime();
      long x = 0;
      for (int i = 0; i < 15_000_000; i++)
        x ^= ThreadLocalRandom.current().nextLong();
      if (x == 0)
        throw new IllegalStateException();
      return System.nanoTime() - time;
    }
  }

  /**
   * Do something on the CPU that creates a lot of garbage, and return the 
   * elapsed time.
   */
  private static class DirtyTask
    implements Callable<Long>
  {
    @Override
    public Long call()
    {
      long time = System.nanoTime();
      String s = "";
      for (int i = 0; i < 10_000; i++)
        s += (int) (ThreadLocalRandom.current().nextDouble() * 13);
      if (s.length() == 10_000)
        throw new IllegalStateException();
      return System.nanoTime() - time;
    }
  }

}


 类似资料:
  • 有人能解释一下新发布的WindowsServiceBus(内部部署,而不是Azure)和NServiceBus之间的区别吗? 寻找详细的答案什么窗口SB可能会丢失,因为我很熟悉NSErviceBus可以做什么: 它是真正的服务总线,而不仅仅是使用队列的消息代理吗? 是否可以支持消息多态?(消息子类化其他消息和支持此层次结构的处理程序 长时间运行的进程和相关性 向外扩展

  • 我正在通过一次发送250个请求来进行API负载测试。 1.配置 很自然,当很多用户同时请求时,服务器需要更长的时间来响应,这是它在这里说的。参见http://jmeter-plugins.org/wiki/responsetimesvsthreads/。然而,当测试这是我发现的… 活动线程与用户请求的数量相同吗?如果是,为什么会在一致的基础上发生? Update-1运行了另一个测试,并增加了这一次

  • 我有一个关于在Java中如何工作的基本问题。 很难看出简单创建并行执行某些任务和将每个任务分配给之间的区别。 看起来使用起来也非常简单和高效,所以我想知道为什么我们不一直使用它。 这只是一种方式比另一种方式执行工作更快的问题吗? 这里有两个非常简单的例子来说明这两种方式之间的区别: 使用executor服务:计数器(任务) 使用executor服务:(创建、提交)

  • 这种方法的Java博士说 如果需要,最多等待给定的时间完成计算,然后检索其结果(如果可用)。 参数: 超时等待的最长时间 unit超时参数的时间单位 根据我的理解,我们对强加了一个超时,我们提交给,这样,我的将在指定的时间(超时)过去后中断 但是根据下面的代码,似乎超过了超时时间(2秒),我真的很难理解这一点。谁能给我指一下正确的路吗?

  • 我们正在尝试对ActiveMQ进行评估,以便在OSB 12c中作为基于JMS的集成使用。我确实关注了一些像https://bizzperform.com/blog/?p=686这样的博客,但是这并没有帮助,反而产生了如下的错误。 有没有人遇到过这种情况,并实现了相同的..金迪建议。

  • 问题内容: 通常,一些答案提到给定的解决方案是 线性的 ,或者另一个是 二次的 。 如何发挥作用/识别什么? 有人能为像我这样仍然不认识的人解释这种最简单的方法吗? 问题答案: 当所需时间随所涉及元素的数量线性增加时,该方法是线性的。例如,用于打印数组元素的for循环大致是线性的: 因为如果我们打印range(100)而不是range(10),则运行它所需的时间要长10倍。您会经常看到写为O(N)