1

I'm trying to make 2 threads one Ping and one Pong. The idea is Ping should always execute first. I'm using synchronized methods. I'm not sure what is wrong with my code here. It looks to me like it should work. I have read up on a lot of documentation. So if you have anything that you think would be of help I'd be happy to read it. I'm sure it's something simple. Any Help Is appreciated

class Ping extends Thread {
   private Table table;
   private String text1 = "";

   public Ping(Table t)
   {
       table = t;
   }
   public void run() {

       for (int i = 0; i < 10; i++) {
           text1= table.getPing();
           System.out.println(text1);
   }
 }
}


class Pong extends Thread {
   private Table table;
   private String text1 = "";

   public Pong(Table t)
   {
       table = t;
   }
   public void run() {
       for (int i = 0; i < 10; i++) {
           text1= table.getPong();
           System.out.println(text1);   }
 }
}

class Table extends Thread {
    private Table table;
    private boolean pinged = false;

    public synchronized String getPong() {
        while (pinged == false) {
            try {
                //System.out.println("WAIT PONG");
                wait();
            } 
            catch (InterruptedException e) 
            { }
        }        
        pinged = false;

        notifyAll();
        String text = "pong";
        return text;
    }

    public synchronized String getPing() {
        while (pinged == true) {
            try {
                wait();
                //System.out.println("WAIT PING");
            } catch (InterruptedException e) { }
        }    
        pinged = true;
        notifyAll();
        String text = "ping";
        return text;
    }
}


public class PingPong {

    //private static final int WAIT_TIME = 200;

    public static void main(String args[]) {

        Table t = new Table();

        Pong pong = new Pong(t);

        Ping ping = new Ping(t);

        System.out.println("main: starting threads...");

        pong.start();
        ping.start();

        System.out.println("main: threads started, sleep a while " +
                           "and wait for termination of Ping and Pong"); 


        System.out.println("both threads terminated");
   }

}

Each result is different but the bizarre thing is I get repeats.

ping
pong
ping
ping
pong
pong
pong
ping
ping
ping
pong
pong
pong
ping
pong
ping
ping
pong
ping
pong
Plisken
  • 423
  • 1
  • 4
  • 20
  • 1
    Seems you have next effect [Synchronization and System.out.println](http://stackoverflow.com/questions/9459657/synchronization-and-system-out-println) – alex2410 Oct 20 '15 at 13:58

3 Answers3

1

The synchronization in your Table class - which by the way does not need to extend Thread - only guarantees that the Ping and Pong threads get their strings in an alternating fashion. It does not guarantee that they print their strings in an alternating fashion.

For example, the following sequence can occur:

Ping gets its first ping, call it ping 1.
Ping prints ping 1.
Pong gets its first pong, call it pong 1.
Ping gets ping 2.
Ping prints ping 2.
Pong prints pong 1.
Pong gets pong 2.
Pong prints pong 2.
Ping gets ping 3.
Pong gets pong 3.
Pong prints pong 3.
Ping prints ping 3.

Note that each thread is alternating between getting its string and printing it, and that the two threads are getting their strings in alternating order. However, between one thread's getting a string and printing the string, the other thread may or may not get time. This results in the alternating sequence being broken up for printing, and in our example the output is:

ping
ping
pong
pong
pong
ping

If you want to fix that, you need to include both getting a string and printing it in the same synchronized block, and you may need that block to synchronize on System.out as well as on Table.

Warren Dew
  • 8,790
  • 3
  • 30
  • 44
0

Try this, this should run Ping first. It will also give you its iteration

 class Ping extends Thread {
 private Table table;
 private String text1 = "";

 public Ping(Table t)
 {
   table = t;
 }
public void run() {

   for (int i = 0; i < 10; i++) {
       text1= table.getPing();
       System.out.println(i + " " + text1);
 }
 }
 }


class Pong extends Thread {
private Table table;
private String text1 = "";

public Pong(Table t)
{
    table = t;
 }

 public void run() {
   for (int i = 0; i < 10; i++) {
       text1= table.getPong();
       System.out.println(i + " " + text1);   }
  }
  }

class Table extends Thread {
private Table table;
private boolean pinged = false;

public synchronized String getPong() {
    while (pinged == false) {
        try {
            //System.out.println("WAIT PONG");
            wait();
        } 
        catch (InterruptedException e) 
        { }
    }        
    pinged = false;

    notifyAll();
    String text = "pong";
    return text;
}

public synchronized String getPing() {
    while (pinged == true) {
        try {
            wait();
            //System.out.println("WAIT PING");
        } catch (InterruptedException e) { }
    }    
    pinged = true;
    notifyAll();
    String text = "ping";
    return text;
   }
 }


    public class PingPong {

   //private static final int WAIT_TIME = 200;

   public static void main(String args[]) {

    Table t = new Table();

    Pong pong = new Pong(t);

    Ping ping = new Ping(t);

    System.out.println("main: starting threads...");

    ping.start();
    pong.start();

    System.out.println("main: threads started, sleep a while " +
                       "and wait for termination of Ping and Pong"); 


    System.out.println("both threads terminated");
   }

   }
Some Java Guy
  • 4,992
  • 19
  • 71
  • 108
0

Use of Synchronous queue in this case should be simple and effective.

import java.util.concurrent.SynchronousQueue;

public class PingPongPattern {



private SynchronousQueue<Integer> q = new SynchronousQueue<Integer>();
    private Thread t1 = new Thread() {

        @Override
        public void run() {
            while (true) {

                // TODO Auto-generated method stub
                super.run();
                try {

                    System.out.println("Ping");
                    q.put(1);
                    q.put(2);
                } catch (Exception e) {

                }
            }
        }

    };

    private Thread t2 = new Thread() {

        @Override
        public void run() {

            while (true) {
                // TODO Auto-generated method stub
                super.run();
                try {
                    q.take();
                    System.out.println("Pong");
                    q.take();

                } catch (Exception e) {

                }

            }

        }

    };

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        PingPongPattern p = new PingPongPattern();
        p.t1.start();
        p.t2.start();
    }

}
Jérôme
  • 1,254
  • 2
  • 20
  • 25