0

I have just started learning threads and pretty new to it.I'm trying to print alphabets and numbers one after the other.I have synchronized them using a flag but of no use.

public class Alphabets {

    public static void main(String[] args) {

              AN an= new AN(false);

              Thread t1=new Thread(new Runnable() {

                @Override
                public void run() {

                    try {

                        an.Alpha();
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            });


              Thread t2= new Thread(new Runnable() {

                @Override
                public void run() {
                    try {
                        an.numbers();
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }

                }
            });


              t1.start();
              t2.start();
    }

}

...

 class AN
    {

        boolean flag;

        AN(boolean flag)
        {
            this.flag=flag;
        }
        synchronized void Alpha() throws InterruptedException
        {
            if(flag==false)
            {
            for(char i='A'; i<='Z';i++)
            {
                System.out.println(+i);
                notifyAll();
                flag=true;
            }
            }
            else
            {
                wait();
            }

        }

        synchronized void numbers() throws InterruptedException
        {
            if(flag==true)
            {
            for(int i=1;i<=26;i++)
            {
                System.out.println(+i);
                notifyAll();
                flag=false;
            }
            }
            else
            {
                wait();
            }
        }


    }

My desired output is : a1b2c3d4....

My console output is : abcd...1234...

Can anybody point out the mistake since I'm unable to synchronize these two threads.

Rahul
  • 3,293
  • 2
  • 31
  • 43
Ankush Dutt
  • 143
  • 8

5 Answers5

0

Change class AN to check the flag in while loop.

public class AN {
  boolean flag;

  AN(boolean flag) {
    this.flag = flag;
  }

  synchronized void Alpha() throws InterruptedException {

    for(char i = 'A'; i <= 'Z'; i++) {
      while(flag == true) {
        wait();
      }
      System.out.println(i);
      notifyAll();
      flag = true;
    }
  }

  synchronized void numbers() throws InterruptedException {

    for(int i = 1; i <= 26; i++) {
      while(flag == false) {
        wait();
      }
      System.out.println(i);
      notifyAll();
      flag = false;
    }
  }
HPCS
  • 1,434
  • 13
  • 22
0

Well, what you want is more or less pipelining, therefore the threads need to know when they are allowed to work.

I'd therefore use a Queue to await the input on one thread and wait for it to be set in the other thread.

Class AN:

import java.util.concurrent.BlockingQueue;

class AN
{

    BlockingQueue<Boolean> input;

    BlockingQueue<Boolean> output;

    AN(BlockingQueue<Boolean> input, BlockingQueue<Boolean> output)
    {

        this.input = input;
        this.output = output;
    }

    void Alpha() throws InterruptedException
    {
        for (char i = 'a'; i <= 'z'; i++) {
            input.take();
            System.out.print(i);
            output.put(Boolean.TRUE);

        }
    }

    void numbers() throws InterruptedException
    {
        for (int i = 1; i <= 26; i++) {
            input.take();
            System.out.print(i);
            output.put(Boolean.TRUE);
        }

    }

}

Class Test (or where your main is):

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

public class Test
{

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

        BlockingQueue<Boolean> input = new LinkedBlockingQueue<>();
        BlockingQueue<Boolean> output = new LinkedBlockingQueue<>();

        AN an1 = new AN(output, input);
        AN an2 = new AN(input, output);
        output.add(Boolean.TRUE);

        Thread t1 = new Thread(new Runnable()
        {

            @Override
            public void run()
            {
                try {
                    an1.Alpha();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        });

        Thread t2 = new Thread(new Runnable()
        {

            @Override
            public void run()
            {
                try {
                    an2.numbers();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }

            }
        });

        t1.start();
        t2.start();

    }
}

Outputs: a1b2c3d4e5f6g7h8i9j10k11l12m13n14o15p16q17r18s19t20u21v22w23x24y25z26

maio290
  • 6,440
  • 1
  • 21
  • 38
  • Thanks for the piece of code but it would be really helpful if you could explain the exact working of BlockingQueue, since i haven't used it nor read about it.As i can see you didn't use synchronized here, so i'm assuming it acts as two different queues which would run one after the other – Ankush Dutt Oct 23 '18 at 13:00
  • 1
    The `take()` method is just waiting until an object is entered into the queue. You can think of it like working at a conveyor belt: You wait for one piece to be in the queue, to continue your work. That's the whole "magic" about it. – maio290 Oct 23 '18 at 13:04
  • Alright! Can you please the explain the main especially these three lines : AN an1 = new AN(output, input); AN an2 = new AN(input, output); output.add(Boolean.TRUE); – Ankush Dutt Oct 30 '18 at 10:30
  • The output of an1 is the input of an2 and the output of an2 is the input of an1. We're adding one element to the list at first - otherwise the threads would only await and not do anything. So the first element is just the "start" switch for the whole process. – maio290 Oct 30 '18 at 16:34
  • what is the significance of this "The output of an1 is the input of an2 and the output of an2 is the input of an1".I mean i couldn't understand this part or the logic behind it. – Ankush Dutt Oct 30 '18 at 17:06
0

You can achieve this by using BlockingQueue and Object's wait and notify methods.

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


    BlockingQueue<String> queue = new ArrayBlockingQueue<String>(10);

    AtomicBoolean flag = new AtomicBoolean(Boolean.TRUE);

    Object lock = new Object();

    Thread t1 = new Thread(new Runnable() {
        @Override
        public void run() {

            try {
                for(int i=1;i<=26;i++){
                        synchronized (lock){
                            while (flag.get()){
                                lock.wait();
                            }
                            System.out.print(i);
                            flag.set(Boolean.TRUE);
                            lock.notify();
                    }
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
    });

    Thread t2 = new Thread(new Runnable() {
        @Override
        public void run() {
            try {
                for(char c='A';c<='Z';c++){
                    synchronized (lock){
                        while (!flag.get()){
                            lock.wait();
                        }
                        System.out.print(c);
                        flag.set(Boolean.FALSE);
                        lock.notify();
                    }
                }

            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
    });


    t1.start();
    t2.start();

    }
}

The above code prints a1b2c3d4.......z26

kiran puppala
  • 689
  • 8
  • 17
0

There are many ways to achieve this, Below one is one of them.

package interview;

public class TestAplhaAndNumberPrinterThreads {

    // created object as static so we can access print method of this class from thread's run methods
    public static TestAplhaAndNumberPrinterThreads output = new TestAplhaAndNumberPrinterThreads();

    private final Object syncer = new Object();
    private int state = 0;

    public void print(char character) throws InterruptedException {
        synchronized (syncer) {
            while (true) {
                if (state == 0) {
                    System.out.print(character + ", ");
                    state = 1;
                    syncer.notify();
                    return;
                } else {
                    syncer.wait();
                }
            }
        }
    }

    public void print(int number) throws InterruptedException {
        synchronized (syncer) {
            while (true) {
                if (state == 1) {
                    System.out.print(number + ", ");
                    state = 0;
                    syncer.notify();
                    return;
                } else {
                    syncer.wait();
                }
            }
        }
    }

    public static void main(String[] args) {
        NumberPrinter numberPrinter = new NumberPrinter();
        AlphabetsPrinter alphabetsPrinter = new AlphabetsPrinter();
        numberPrinter.start();
        alphabetsPrinter.start();
    }
}

class NumberPrinter extends Thread {

    @Override
    public void run() {
        try {
            for (int i = 1; i <= 26; i++) {
                TestAplhaAndNumberPrinterThreads.output.print(i);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

class AlphabetsPrinter extends Thread {

    @Override
    public void run() {
        try {
            for (char i = 'a'; i <= 'z'; i++) {
                TestAplhaAndNumberPrinterThreads.output.print(i);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

// output: a, 1, b, 2, c, 3, d, 4, e, 5, f, 6, g, 7, h, 8, i, 9, j, 10, k, 11, l, 12, m, 13, n, 14, o, 15, p, 16, q, 17, r, 18, s, 19, t, 20, u, 21, v, 22, w, 23, x, 24, y, 25, z, 26,
0

I think the big things is for you to know, how to use break points to debug in IDE and why your code was not working. You can see the process of your code will run. I have post the picture at the last and this code which will work like your wish

class AN {

boolean flag;

AN(boolean flag) {
    this.flag = flag;
}

synchronized void Alpha() throws InterruptedException {
    if (flag == false) {
        for (char i = 'A'; i <= 'Z'; i++) {
            System.out.println(i);
            flag = true;
            notify();
            wait();
        }
    }

}

synchronized void numbers() throws InterruptedException {
    if (flag == true) {
        for (int i = 1; i <= 26; i++) {
            System.out.println(+i);
            flag = false;
            notify();
            wait();
        }
    }
}

}

enter image description here