java - 为什么我的多线程代码会导致挂起?

标签 java multithreading concurrency

我研究java并发。

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

我的代码:

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

然后挂起。

我不知道为什么。

请帮忙。

最佳答案

它不会挂起,启动 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 毫秒,而执行时间只有几分钟。这是因为启动线程比对锁存器进行倒计时或读取或写入单个数组元素要昂贵得多,而且您只能测量后者。

关于java - 为什么我的多线程代码会导致挂起?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31905083/

相关文章:

java - 将用户添加到 spring 3 security

C#处理二进制文件、多线程处理

c# - 在此 ConcurrentDictionary 缓存场景中是否需要锁定

concurrency - 如何在 Erlang 中对方法应用超时?

python - celery :任务层次结构后的回调

java - 如何使用 Selenium 选择 javascript 选项卡?

Java 集合静态方法 min

.net - Socket ReceiveFromAsync 是隐式多线程的吗?

concurrency - 哪些挑战促进了并行/并发架构的使用?

java - JSP 中的页眉、页脚、左侧和右侧模板