-1

Hi I am trying to print even and odd using two threads namedly EvenThread and OddThread, some times I am getting correct result and some times not, could any one please help me.

package com.java8;

public class EvenOddExample {

    public static synchronized void print(int i,String name){
            System.out.println(i+"--->"+name);
    }
    public static void main(String[] args) throws InterruptedException {
        EvenThread e=   new EvenThread();
        e.start();
        OddThread o=new OddThread();
        o.start();

    }
    public static class EvenThread extends Thread{

        public void run() {
            for(int i=0;i<10;i++){
                if(i%2==0){
                    print(i,"Even");
                }else{
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }

        }

    }

    public static class OddThread extends Thread{

        @Override
        public void run() {
            for(int i=1;i<10;i++){
                if(i%2!=0){
                    print(i,"Odd");
                }else{
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }

        }

    }
}
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
ASR
  • 3,289
  • 3
  • 37
  • 65
  • 4
    What does "correct result" mean? – Michał Krzywański Aug 01 '19 at 06:39
  • have eventhread start with 2 and oddThread with one, loop over (print -> add 2 to value) – Stultuske Aug 01 '19 at 06:40
  • changed but same happening 1--->Odd 2--->Even 3--->Odd 4--->Even 6--->Even 5--->Odd 8--->Even 7--->Odd 9--->Odd – ASR Aug 01 '19 at 06:46
  • 1
    You mean that sometimes `print` prints several odd numebers in a row for example? Because you put `synchronized` on static method so those two threads will synchronize on `EvenOddExample.class` object when invoking `print`. And that does not mean that one thread cannot invoke `print` several times in a row. – Michał Krzywański Aug 01 '19 at 06:46
  • yes @michalk exactly the problem is – ASR Aug 01 '19 at 06:48
  • https://stackoverflow.com/questions/32010904/what-will-happen-to-the-request-for-synchronized-block-in-java-if-monitor-is-alr this post might clear your doubt. – Ifthikar Aug 01 '19 at 07:53
  • If one of the answers below fixes your issue, you should accept it (click the check mark next to the appropriate answer). That does two things. It lets everyone know your issue has been resolved to your satisfaction, and it gives the person that helps you credit for the assist. [See here](http://meta.stackexchange.com/a/5235) for a full explanation. – dpr Aug 06 '19 at 07:28

3 Answers3

2

You need some signaling between the two threads. Putting synchronized on the print method simply guarantees, that only one thread can enter the method at a time. To put your threads into order Object.wait() and Object.notify{All}() methods can be used.

Actually this is some kind of the Sender-Receiver Synchronization Problem. Based on the example of the problem described here (Please read this page in order to understand how this synchronization works) I adapted your code. Additionally I used ExecutorService and Callable instead of extending Thread, which is bad-practice:

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class EvenOddExample {

  private static boolean evensTurn = true;
  private static Object monitor = new Object();

  public static void print(int i, String name) {
    System.out.println(i + "--->" + name);
  }

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

    final ExecutorService executorService = Executors.newFixedThreadPool(2);
    executorService.submit(new EvenCallable());
    executorService.submit(new OddCallable());
    executorService.shutdown();
  }

  public static class EvenCallable implements Callable<Void> {

    @Override
    public Void call() throws InterruptedException {
      for (int i = 0; i < 10; i++) {
        if (i % 2 == 0) {
          synchronized (monitor) {
            while (!evensTurn) { // not your turn?
              monitor.wait(); // wait for monitor in a loop to handle spurious wakeups
            }
            print(i, "Even");
            evensTurn = false; // next odd needs to run
            monitor.notifyAll(); // wakeup the odd thread
          }
        } else {
          Thread.sleep(1000);
        }
      }
      return null;
    }
  }

  public static class OddCallable implements Callable<Void> {

    @Override
    public Void call() throws InterruptedException {
      for (int i = 1; i < 10; i++) {
        if (i % 2 != 0) {
          synchronized (monitor) {
            while (evensTurn) {
              monitor.wait();
            }
            print(i, "Odd");
            evensTurn = true;
            monitor.notifyAll();
          }
        } else {
          Thread.sleep(1000);
        }
      }
      return null;
    }
  }
}
dpr
  • 10,591
  • 3
  • 41
  • 71
1

synchronized is used to lock the access of another thread, when the locked object is free, it does not guarantee which is next called thread. You can use semaphore to make inter-thread communication:

  private static Semaphore[] semaphores = {new Semaphore(0), new Semaphore(1)};

  static void print(int i, String name) {
    try {
      semaphores[(i + 1) % 2].acquire();
    } catch (InterruptedException e) {
      Thread.currentThread().interrupt();
    }
    System.out.println(i + "--->" + name);
    semaphores[i % 2].release();
  }
yelliver
  • 5,648
  • 5
  • 34
  • 65
0
public class EvenOddPrinter {
    static boolean flag = true;

    public static void main(String[] args) {
        class Odd implements Runnable {

            @Override
            public void run() {
                for (int i = 1; i <= 10;) {
                    if (EvenOddPrinter.flag) {
                        System.out.println(i + "--->odd");
                        i += 2;
                        EvenOddPrinter.flag = !EvenOddPrinter.flag;
                    }
                }
            }

        }

        class Even implements Runnable {

            @Override
            public void run() {
                for (int i = 2; i <= 10;) {
                    if (!EvenOddPrinter.flag) {
                        System.out.println(i + "---->even");
                        i += 2;
                        EvenOddPrinter.flag = !EvenOddPrinter.flag;
                    }
                }

            }

        }
        Runnable odd = new Even();
        Runnable even = new Odd();
        Thread t1 = new Thread(odd, "Odd");
        Thread t2 = new Thread(even, "Even");
        t1.start();
        t2.start();
    }
}
ASR
  • 3,289
  • 3
  • 37
  • 65
  • Yes, by doing this you will probably skip half of the numbers – dpr Aug 02 '19 at 11:20
  • This is definitely wrong!!!, where's you sleep()? you can try adding sleep() with different delays, you will see sometimes it's stuck, cannot print to 10 – yelliver Aug 08 '19 at 07:08