性能上的线程开销

时间:2015-05-08 09:23:16

标签: java multithreading

我正在尝试通过添加线程来执行并发任务来提高应用程序的性能。我得到的结果对我来说非常混乱,让我觉得有一些线程相关的开销,我不知道。下面是相同代码的两个副本,除了一个使用线程而另一个不使用。不使用线程的线程比使用线程的线程快四倍。我正在使用我的设备进行测试,这是带有四核处理器的三星note 4。任何见解都将受到高度欢迎。

谢谢,

CWM

  public void testThreads() throws InterruptedException {
  startMilli = System.currentTimeMillis();
  Thread t1 = new Thread() {
        public void run() {
            load1();
        }
    };

    Thread t2 = new Thread() {
        public void run() {
            load2();
        }
    };
    t1.start();
    t2.start();
    t1.join();
    t2.join();
  //  load1();
  //  load2();
    stopMilli = System.currentTimeMillis();
    diffMilli = stopMilli - startMilli;
    startMilli = System.currentTimeMillis();
}
public void load1() {
    List<Integer> list1 = new ArrayList<Integer>();
    for(i = 0; i<100000; i++) {
        list1.add(i);
    }
}

public void load2() {
    List<Integer> list2 = new ArrayList<Integer>();
    for(j = 100000; j<200000; j++){
        list2.add(j);
    }
}

  public void testThreads() throws InterruptedException {
  startMilli = System.currentTimeMillis();

    load1();
    load2();
    stopMilli = System.currentTimeMillis();
    diffMilli = stopMilli - startMilli;
    startMilli = System.currentTimeMillis();
}
public void load1() {
    List<Integer> list1 = new ArrayList<Integer>();
    for(i = 0; i<100000; i++) {
        list1.add(i);
    }
}

public void load2() {
    List<Integer> list2 = new ArrayList<Integer>();
    for(j = 100000; j<200000; j++){
        list2.add(j);
    }
}

1 个答案:

答案 0 :(得分:0)

我不确定,但我认为操作系统内存管理是你的问题所在。在第一种方法中,您将在每个List中同时添加100000个元素。因此两个线程同时调用resize操作,这可能会锁定内存,同时为较大的List找到新的空间,使其他线程等待。在第二种方法中,顺序添加200000个元素,因此不会发生两个同时的调整大小操作并且没有锁定存储器。

我为更大的套装进行了测试。 Array比List实现稍快。

以下是总计100000000次内存访问操作的结果

using array/arraylist

thread x4:    83 / 20000 ms  // each thread got 25000000 size chunk
thread x2:    75 / 22000 ms  // each thread got 50000000 size chunk
main thread:  146/ 25800 ms  // main thread processed all elements in one arraylist

但是当我用range/2个元素填充两次arraylist时,时间从25800减少到10100 ms。

int range = 100000000;
public static void main(String[] args) throws InterruptedException {
    TEST m = new TEST();
    m.testThreads1(); // m.testThreads();
}

public void testThreads() throws InterruptedException {
    long startMilli = System.currentTimeMillis();
    Thread t1 = new Thread() {
        public void run() {
            load1();
        }
    };
    Thread t2 = new Thread() {
        public void run() {
            load1();
        }
    };
    Thread t3 = new Thread() {...}
    Thread t4 = new Thread() {...}
    t1.start();
    t2.start();
    t3.start();
    t4.start();
    t1.join();
    t2.join();
    t3.join();
    t4.join();

    long stopMilli = System.currentTimeMillis();
    System.out.println(stopMilli - startMilli);
}

public void load1() {
    List<Integer> list1 = new ArrayList<Integer>();
    // int[] arr = new int[range];  // change size according to thread #
    for(int i = 0; i<range/2; i++) {
        list1.add(i);
        // arr[i]=i;
    }
}

public void testThreads1() throws InterruptedException {
    long startMilli = System.currentTimeMillis();

    /* 2 load1 call for `range/2` elements performes better than 1 call for `range` elements */
    load1();
    load1();
    long stopMilli = System.currentTimeMillis();
    System.out.println(stopMilli - startMilli);
}
相关问题