为什么我的多线程代码会挂起?

时间:2015-08-09 14:04:57

标签: java multithreading concurrency

我研究java concurency。

我试图估计时间执行取决于线程数(读和写)

我的代码:

public class Task5 {
    public static int [] readerThreadCount = {1,10,100,1000};
    public static int [] writerThreadCount = {10, 1000, 1000000};


    public static void main(String[] args) throws InterruptedException {
        for (int readCount : readerThreadCount) {
            for (int writeCount : writerThreadCount) {
                System.out.println(readCount + "/" + writeCount + " = " + test(readCount, writeCount, new ArrayHolderBySynchronized()));
            }
        }

    }

    private static long test(int readCount, int writeCount, ArrayHolder arrayHolder) throws InterruptedException {
        CountDownLatch countDownLatch = new CountDownLatch(readCount + writeCount);
        List<Thread> threads = new ArrayList<>();
        for (int i = 0; i < readCount; i++) {
            threads.add(new Thread(new ArrayReader(arrayHolder, countDownLatch)));
        }
        for (int i = 0; i < writeCount; i++) {
            threads.add(new Thread(new ArrayWriter(arrayHolder, countDownLatch)));

        }
        for(Thread thread:threads){
            thread.start();
        }
        countDownLatch.await();//all threads started
        long start = System.currentTimeMillis();
        for (Thread thread : threads) {
            thread.join();
        }
        return System.currentTimeMillis() - start;

    }
}

class ArrayHolderBySynchronized extends ArrayHolder {

    @Override
    public synchronized int get(int index) {
        return arr[index];
    }

    @Override
    public synchronized void write(int index, int value) {
        arr[index] = value;
    }
}

class ArrayReader implements Runnable {
    ArrayHolder arrayHolder;
    CountDownLatch countDownLatch;

    ArrayReader(ArrayHolder arrayHolder, CountDownLatch countDownLatch) {
        this.arrayHolder = arrayHolder;
        this.countDownLatch = countDownLatch;
    }

    @Override
    public void run() {
        countDownLatch.countDown();
        arrayHolder.get(new Random().nextInt(ArrayHolder.ARRAY_SIZE));
    }
}

class ArrayWriter implements Runnable {
    ArrayHolder arrayHolder;
    CountDownLatch countDownLatch;

    ArrayWriter(ArrayHolder arrayHolder, CountDownLatch countDownLatch) {
        this.arrayHolder = arrayHolder;
        this.countDownLatch = countDownLatch;
    }

    @Override
    public void run() {
        countDownLatch.countDown();
        arrayHolder.write(new Random().nextInt(ArrayHolder.ARRAY_SIZE), -1);
    }
}

abstract class ArrayHolder {
    public static int ARRAY_SIZE = 1_000_000;
    protected int[] arr = generateArray();

    private int[] generateArray() {
        int[] arr = new int[ARRAY_SIZE];
        for (int i = 0; i < ARRAY_SIZE; i++) {
            arr[i] = i + 1;
        }
        return arr;
    }

    public abstract int get(int index);

    public abstract void write(int index, int value);
}

输出

1/10 = 0
1/1000 = 1

并挂起。

我没有想法。

请帮忙。

1 个答案:

答案 0 :(得分:1)

它没有挂起,启动1000000个线程只需要比启动1000个线程(在我的机器上几分钟)长1000倍:

> java Task5

1/10 = 0
1/1000 = 1
1/1000000 = 63
10/10 = 0
10/1000 = 0
10/1000000 = 60
100/10 = 0
100/1000 = 0
100/1000000 = 63
1000/10 = 0
1000/1000 = 0
1000/1000000 = 60

您的下一个问题可能就是为什么您的测试报告执行时间需要几分钟的持续时间为60毫秒。那是因为启动线程比倒计时器,或读取或写入单个数组元素要昂贵得多,而且只测量后者。