简体   繁体   中英

print even and odd using 2 threads

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

        }

    }
}

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

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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