为什么不加入线程?

时间:2015-08-09 15:15:36

标签: java multithreading join concurrency

我想测量线程执行

我写了以下代码:

public class Task5 {
    public static int [] readerThreadCount = {10};
    public static int [] writerThreadCount = {1};


    public static void main(String[] args) throws InterruptedException {
        for (int readCount : readerThreadCount) {
            for (int writeCount : writerThreadCount) {
                test(readCount, writeCount, new ArrayHolderBySynchronized());
            }
        }

    }

    private static void test(int readCount, int writeCount, ArrayHolder arrayHolder) throws InterruptedException {
        final List<Thread> threads = new ArrayList<>();
        CyclicBarrier cyclicBarrier = new CyclicBarrier(1, new Summarizer(threads, readCount, writeCount));
        for (int i = 0; i < readCount; i++) {
            threads.add(new Thread(new ArrayReader(arrayHolder, cyclicBarrier)));
        }
        for (int i = 0; i < writeCount; i++) {
            threads.add(new Thread(new ArrayWriter(arrayHolder, cyclicBarrier)));

        }

        for(Thread thread:threads){
            thread.start();
        }

    }
}

class Summarizer implements Runnable{
    List<Thread> threads;
    int readCount;
    int writeCount;
    Summarizer(List<Thread> threads, int readCount, int writeCount) {
        this.threads = threads;
        this.readCount = readCount;
        this.writeCount = writeCount;
    }

    @Override
    public void run() {
        long start = System.currentTimeMillis();
        System.out.println("All threads started");
        for (Thread thread : threads) {
            try {
                thread.join();
            } catch (InterruptedException e) {
                e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
            }
        }
        System.out.println(readCount + "/" + writeCount + (System.currentTimeMillis() - start));
    }
}
class ArrayHolderBySynchronized extends ArrayHolder {

    @Override
    public synchronized int get(int index) {
        System.out.println("read");
        return arr[index];
    }

    @Override
    public synchronized void write(int index, int value) {
        System.out.println("write");
        arr[index] = value;
    }
}

class ArrayReader implements Runnable {
    ArrayHolder arrayHolder;
    CyclicBarrier cyclicBarrier;

    ArrayReader(ArrayHolder arrayHolder, CyclicBarrier cyclicBarrier) {
        this.arrayHolder = arrayHolder;
        this.cyclicBarrier = cyclicBarrier;
    }

    @Override
    public void run() {
        try {
            cyclicBarrier.await();
        } catch (InterruptedException e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        } catch (BrokenBarrierException e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        }
        arrayHolder.get(new Random().nextInt(ArrayHolder.ARRAY_SIZE));
    }
}

class ArrayWriter implements Runnable {
    ArrayHolder arrayHolder;
    CyclicBarrier cyclicBarrier;

    ArrayWriter(ArrayHolder arrayHolder, CyclicBarrier cyclicBarrier) {
        this.arrayHolder = arrayHolder;
        this.cyclicBarrier = cyclicBarrier;
    }

    @Override
    public void run() {
        try {
            cyclicBarrier.await();
        } catch (InterruptedException e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        } catch (BrokenBarrierException e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        }
        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);
}

但在输出中我看到了

All threads started

但是应用程序挂起在thread.join。

我错了什么?

1 个答案:

答案 0 :(得分:0)

您的代码中存在死锁:

您将Summarizer实例作为barrierAction提交给CyclicBarrier。因此,当屏障跳闸时,它必须在等待屏障的任何线程被允许继续之前执行Summarizer。 但是 Summarizer会在等待CyclicBarrier的所有线程上执行thread.join()。

所以CyclicBarrier正在等待Summarizer。 Summarizer正在等待线程。并且线程正在等待CyclicBarrier。