PingPong程序Java多线程

时间:2017-07-21 09:18:31

标签: multithreading

我正在尝试学习多线程的基本概念。

为什么我的乒乓程序只打印Ping0& Pong0,为什么notify()不启动处于等待状态的Ping线程?

公共类PingPong实现Runnable {       字符串;

  public PingPong(String word) {
    this.word = word;
  }

  public void run() {

    synchronized (this) {
      for (int i = 0; i < 10; i++) {
        System.out.println(word + i);
        try {
          wait(); 
          notifyAll();
        } catch (Exception e) {
          System.out.println(e.getMessage());
        }
      }
    }
  }

  public static void main(String[] args) {

    Runnable p1 = new PingPong("ping");
    Thread t1 = new Thread(p1);
    t1.start();

    Runnable p2 = new PingPong("pong");
    Thread t2 = new Thread(p2);
    t2.start();

  }

}

输出

ping0
pong0

我尝试删除wait()并打开ping pong直到循环结束。但这是否保证会按顺序打印?

为什么wait()后跟notify()不要求ping1线程开始执行?

4 个答案:

答案 0 :(得分:3)

  1. 如果你看到jstack,你可以看到thread-0和thread-1正在等待不同的锁。这是因为你的p1和p2是不同的对象,所以当你使用synchronized (this)时,它们不会竞争同一个锁,所以通知这种方式不会起作用。尝试使用另一个对象作为锁。
  2. 等待通知后再运行。当两个线程进入等待状态时,没有其他线程可以通知它们。
  3. 试试这段代码:

    String word;
    Object a;
    public PingPong(String word, Object a) {
        this.word = word;
        this.a = a;
    }
    
    public void run() {
    
        synchronized (a) {
            for (int i = 0; i < 10; i++) {
                System.out.println(word + i);
                try {
    
                    a.notifyAll();
                    a.wait();
                } catch (Exception e) {
                    System.out.println(e.getMessage());
                }
            }
        }
    }
    
    public static void main(String[] args) throws InterruptedException {
    
        Object a = new Object();
        Runnable p1 = new PingPong("ping", a);
        Thread t1 = new Thread(p1);
        t1.start();
    
        Runnable p2 = new PingPong("pong", a);
        Thread t2 = new Thread(p2);
        t2.start();
    
    }
    

答案 1 :(得分:1)

这是使用线程池执行器的类似解决方案:

public class PingPong implements Runnable {
    String word;
    Lock lock;

    public PingPong(String word, Lock lock) {
        this.word = word;
        this.lock = lock;
    }

    @Override
    public void run() {
        while(true){
            System.out.println("Received : " + word);
            lock.notifyAll();
            try {
                lock.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        ExecutorService ex = Executors.newFixedThreadPool(2);
        Lock lock = new ReentrantLock();
        while(true){
            ex.submit(new PingPong("ping", lock));
            ex.submit(new PingPong("pong", lock));
        }
    }
}

答案 2 :(得分:0)

以下解决方案基于:

  • Java内部API
  • 执行顺序

    public class Test {
    
    public static void main(String[] args) {
        SynchronousQueue<String> queue = new SynchronousQueue<>();
    
        Thread ping = new Thread(new Task(queue, "ping", "ping"));
        ping.setName("ping thread");
        ping.start();
    
        Thread pong = new Thread(new Task(queue, "pong", "ping"));
        pong.setName("pong thread");
        pong.start();
    
    
    }
    
    private static class Task implements Runnable {
        private SynchronousQueue<String> queue;
        private String command;
        private String step;
    
        Task(SynchronousQueue<String> queue, String command, String step) {
            this.queue = queue;
            this.command = command;
            this.step = step;
        }
    
        @Override
        public void run() {
            try {
                if (command.equals(step)) {
                    doCommandAndWaitRepeatedly();
                } else {
                    waitAndDoCommandRepeatedly();
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
    
        private void doCommandAndWaitRepeatedly() throws InterruptedException {
            while (true) {
                queue.offer(command, 1, TimeUnit.SECONDS);
                Thread.sleep(500);
                System.out.println(Thread.currentThread().getName() + ":" + queue.poll(1, TimeUnit.SECONDS));
            }
        }
    
        private void waitAndDoCommandRepeatedly() throws InterruptedException {
            while (true) {
                System.out.println(Thread.currentThread().getName() + ":" + queue.poll(1, TimeUnit.SECONDS));
                Thread.sleep(500);
                queue.offer(command, 1, TimeUnit.SECONDS);
            }
        }
    }
    

    }

答案 3 :(得分:0)

class Ping extends Thread
{
    public void run()
    {        
        for(int i=1;i<=5;i++)
        {
            System.out.println("PING");
            try{
                  sleep(2000);
            }  catch(Exception e){}
        }       
     }
}

class Pong extends Thread
{
    public void run() 
    {
        for (int i=1;i<=5;i++)
        {
            System.out.println("PONG");
            try{
                sleep(2000);
            }  catch(Exception e){}
        }
    }
}

public class PingPong
{
    public static void main(String... args) throws Exception
    {
        Ping p1=new Ping();
        Pong p2=new Pong();
        p1.start();
        Thread.sleep(1000);  //super important for proper sequence
        p2.start();  
        p1.join();
    }
}