使用wait / notify执行顺序线程

时间:2018-04-08 18:37:20

标签: java multithreading java-threads

现在我正在努力完成标题中的任务。我创建了X个线程,每个线程在周期中Z次打印Y个相等的数字(从构造函数中获取,例如" 11111"," 222222"等)。结果如下:

111111111
222222222
333333333
111111111
222222222
333333333

对于X = 3,Y = 9且Z = 2。 首先,我使用睡眠,中断和传递解决了这个问题" next"线程到前一个的构造函数。一个中断另一个等。下一步是使用wait / notify而不是sleep和interrupt来获得相同的输出。据我所见,创建共享监视器对象,在每次打印之后以及在某个时刻调用等待都是必要的。我应该调用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();
    }

}

你能帮助改善它吗?我发现了类似的任务,但他们没有包含适当的答案。感谢。

最终解决方案基于纳迪尔的答案:

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

1 个答案:

答案 0 :(得分:3)

可以使用用于同步线程的类来完成(甚至确保它们是orderer)。所有线程都将共享同一个实例。

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用于强制执行订单。