0

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. 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. 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:

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;
    }
}
3
  • Use a CyclicBarrier or a Phaser. Commented Apr 8, 2018 at 19:18
  • Is it a requirement of the exercise that you use wait/notify, or are you allowed to use utilities like Semaphore? Commented Apr 8, 2018 at 21:06
  • Yes, just wait/notify. Commented Apr 8, 2018 at 21:16

1 Answer 1

3

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. Then you would put the code for printing, and afterwards, you would call threadDone(), allowing the next thread to be released. The id is used to enforce an order.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.