奇数打印带有控制线程的线程

问题描述 投票:0回答:1

我在下面编写了程序,其中even线程将打印偶数,而odd线程将打印奇数。除了奇数和偶数线程外,我还创建了一个control线程,该线程确定数字是奇数还是偶数,并适当地设置标志。根据控制线程设置的标志,oddeven线程都将有机会打印。

我正在使用数组作为源。控制线程将index递增,因此奇数或偶数线程可以从数组中检索数字并打印。

下面是完整的代码,注释很好。


package com.example.practice;


public class OddEvenDemoVer2 {

    // Since all of these variable are used in a synchronized block, I think we
    // don't need them to be as volatile, as synchronized enforces
    // memory-barrier and hence all thread would see latest values.

    static boolean printEven = false;
    static boolean printingDone = false;
    static int index = 0;

    static volatile boolean stop = false;

    static volatile boolean oddThreadStarted = false;
    static volatile boolean evenThreadStarted = false;

    public static void main(String[] args) throws InterruptedException {

        Object _controlLock = new Object();
        Object _indexControlLock = new Object();

        int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

        class ControlThread implements Runnable {

            @Override
            public void run() {

                // Wait for proper initialization of odd and even threads.
                while (!oddThreadStarted && !evenThreadStarted) {
                    try {
                        Thread.sleep(50);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }

                for (; !stop;) {

                    // This is to make sure that we give chance to OddThread or
                    // EvenThread to print the values.

                    // Here, we are only setting the flag which thread should
                    // print the number, the advancing of index is done in
                    // another block.
                    synchronized (_controlLock) {

                        if (arr[index] % 2 == 0) {
                            printEven = true;
                        }
                        else {
                            printEven = false;
                        }
                        _controlLock.notifyAll();
                    }

                    // This is to make sure we advance index only when printing
                    // has been done either by OddThread or EvenThread
                    synchronized (_indexControlLock) {
                        while (printingDone != true) {
                            try {
                                _indexControlLock.wait();
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                        index++;
                        if (index > 9) {
                            stop = true;
                        }
                    }
                }
            }
        }

        class EvenPrintingThread implements Runnable {

            @Override
            public void run() {
                evenThreadStarted = true;

                // Loop until stop is signaled by ControlThread
                for (; !stop;) {

                    synchronized (_controlLock) {
                        while (printEven != true) {
                            try {
                                _controlLock.wait();
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                        System.out.println("Even printing thread --> " + arr[index]);

                        // This is to signal control thread that printing has
                        // been done and now index can be advanced.
                        synchronized (_indexControlLock) {
                            printingDone = true;
                            _indexControlLock.notify();
                        }
                    }
                }
            }
        }

        class OddPrintingThread implements Runnable {

            @Override
            public void run() {
                oddThreadStarted = true;

                // Loop until stop is signaled by ControlThread
                for (; !stop;) {

                    synchronized (_controlLock) {
                        while (printEven != false) {
                            try {
                                _controlLock.wait();
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }

                        System.out.println("Odd printing thread --> " + arr[index]);

                        // This is to signal control thread that printing has
                        // been done and now index can be advanced.
                        synchronized (_indexControlLock) {
                            printingDone = true;
                            _indexControlLock.notify();
                        }
                    }
                }
            }
        }

        Thread controlThread = new Thread(new ControlThread());

        controlThread.start();

        Thread evenThread = new Thread(new EvenPrintingThread());
        Thread oddThread = new Thread(new OddPrintingThread());

        evenThread.start();
        oddThread.start();

        Thread.sleep(1000000L);
    }
}

我希望该程序可以运行,但是行为异常。例如,输出之一是:

Odd printing thread --> 1
Odd printing thread --> 1

Odd printing thread --> 1
Odd printing thread --> 1

...

Odd printing thread --> 1
Odd printing thread --> 1
Odd printing thread --> 1
Odd printing thread --> 10
Odd printing thread --> 10
Odd printing thread --> 10
Odd printing thread --> 10

我在网上看到了解决相似问题的其他一些方法,但是,当我开始研究此方法(无需在线寻找现成的解决方案)时,我想到了上述方法。我不想仅仅因为它不起作用而放弃。我进行了调试,但是不清楚这种方法可能出什么问题。

我想念什么?

编辑

附加显示两个线程“拥有”相同对象ID的屏幕快照。

Screen shot of debug

java multithreading
1个回答
2
投票

根据预期的行为,它只需要更改一两个即可。

© www.soinside.com 2019 - 2024. All rights reserved.