【问题标题】:Why does my multithreaded code leads to hang?为什么我的多线程代码会导致挂起?
【发布时间】:2015-08-09 14:04:57
【问题描述】:

我学习 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 个核心。
  • 是的。产生 1000000 个线程是无稽之谈。您通常会选择与处理器的并发能力相等的线程数,您可以将其视为核心数,然后平衡它们之间的工作负载。对于四核 -> 4 线程。
  • 对于像这样的 CPU 密集型任务,产生比核心更多的线程绝对没有意义。产生线程很昂贵; 1000000 太高了。

标签: java multithreading concurrency


【解决方案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 毫秒的持续时间,而执行时间却是几分钟。这是因为启动线程比倒计时锁存器或读取或写入单个数组元素要昂贵得多,而且您只测量后者。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多