简体   繁体   English

使用等待/通知顺序执行线程

[英]Sequential thread execution using wait/notify

Now I'm struggling with the task from the title. 现在,我正在努力处理标题中的任务。 I create X threads, each of them prints Y equal digits (getting from constructor, for example "11111", "222222" etc) for Z times in cycle. 我创建了X个线程,每个线程在Z周期内打印Y个相等的数字(从构造函数中获取,例如“ 11111”,“ 222222”等)。 So the result looks like: 所以结果看起来像:

111111111
222222222
333333333
111111111
222222222
333333333

for X = 3, Y = 9 and Z = 2. Firstly I've solved this issue using sleep, interrupt and passing "next" thread to the constructor of previous one. 对于X = 3,Y = 9和Z =2。首先,我使用睡眠,中断并将“下一个”线程传递给前一个构造函数来解决此问题。 One interrupts another etc. Next step is to get the same output using wait/notify instead sleep and interrupt. 一个中断另一个中断,等等。下一步是使用等待/通知代替睡眠和中断来获得相同的输出。 As far as I can see, it's neccesary to create the shared monitor object, to invoke wait after every printing and in a some moment " I should invoke notifyAll. Current code is: 据我所知,有必要创建共享监视器对象,在每次打印后调用等待,并且稍后“我应该调用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();
    }

}

Could you help to improve it? 您能帮助改善它吗? I found similar tasks but they don't contain appropriate answers. 我发现了类似的任务,但其中没有适当的答案。 Thanks. 谢谢。


Final solution based on the Nadir's answer: 根据天底答案的最终解决方案:

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;
    }
}

It can be accomplished with a class used to synchronize the threads (and even make sure they are orderer). 可以使用用于同步线程的类(甚至确保它们是有序的)来实现的。 All threads would share the same instance. 所有线程将共享同一实例。

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();
        }
    }
}

On your thread's run() , you would call doSync() before printing anything. 在线程的run() ,您将在打印任何内容之前调用doSync() Then you would put the code for printing, and afterwards, you would call threadDone() , allowing the next thread to be released. 然后,您将放置代码以进行打印,然后,您将调用threadDone() ,以允许释放下一个线程。 The id is used to enforce an order. 该ID用于强制执行订单。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM