使用 wait/notify 的顺序线程执行

Sequential thread execution using wait/notify

现在我正在努力完成标题中的任务。我创建了 X 个线程,每个线程在循环中打印 Z 次相同的数字(从构造函数获取,例如“11111”、“222222”等)。所以结果看起来像:

111111111
222222222
333333333
111111111
222222222
333333333

对于 X = 3、Y = 9 和 Z = 2。 首先,我使用睡眠、中断并将 "next" 线程传递给前一个构造函数解决了这个问题。一个中断另一个等等。下一步是使用 wait/notify 而不是睡眠和中断来获得相同的输出。据我所知,创建共享监视器 object 是必要的,以便在每次打印后调用等待,并且在某个时刻“我应该调用 notifyAll。 当前代码是:

public class PrinterController {

    private static final int THREADS_NUMBER = 5;

    public static void main(String[] args) {

        Printer[] printers = new Printer[THREADS_NUMBER];
        for (int i = 0; i < THREADS_NUMBER; i++) {
            printers[i] = new Printer(i);
            printers[i].start();
        }
    }
}   

public class Printer extends Thread {

    private static int portion = 10;
    private static int totalNumber = 100;
    private int digit;
    private static final Object monitor = new Object();

    public Printer(int digit) {
        this.digit = digit;
    }

    @Override
    public void run() {
        synchronized (monitor) {
            int portionsNumber = totalNumber / portion;
            for (int i = 0; i < portionsNumber; i++) {
                printLine();
                try {
                    monitor.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private void printLine() {
        for (int j = 0; j < portion; j++) {
            System.out.print(digit);
        }
        System.out.println();
    }

}

你能帮忙改进一下吗?我找到了类似的任务,但它们不包含适当的答案。谢谢


基于 Nadir 的回答的最终解决方案:

public class Printer extends Thread {

    private static int portion = 10;
    private static int totalNumber = 100;
    private int digit;
    static Object monitor = new Object();
    static Integer counter = 0;

    public Printer(int digit) {
        this.digit = digit;
    }

    @Override
    public void run() {
        int portionsNumber = totalNumber / portion;
        for (int i = 0; i < portionsNumber; i++) {
            synchronized (monitor) {
                while (digit != counter) {
                    try {
                        monitor.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                printLine();
                monitor.notifyAll();
            }
        }
    }

    private void printLine() {
        for (int j = 0; j < portion; j++) {
            System.out.print(digit);
        }
        System.out.println();
        counter = (counter + 1) % PrinterController.THREADS_NUMBER;
    }
}

它可以通过用于同步线程(甚至确保它们是排序者)的 class 来完成。所有线程将共享同一个实例。

public class Synchronizer 
{
    private int nextThread;
    private int maxNumThreads;

    public Synchronizer(int numThreads)
    {
        maxNumThreads = numThreads;
        nextThread = 0;
    }

    public void doSync(int threadId) throws Exception
    {
        synchronized(this)
        {
            while(nextThread != threadId)
            {
                wait();
            }
        }
    }

    public void threadDone(int threadId) throws Exception
    {
        synchronized(this)
        {
            nextThread = (threadId + 1) % maxNumThreads;
            notifyAll();
        }
    }
}

在您的线程 run() 上,您会在打印任何内容之前调用 doSync()。然后你会把打印的代码,然后你会调用threadDone(),让下一个线程被释放。 id 用于执行命令。