Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/oracle/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Multithreading 乒乓球程序Java多线程_Multithreading - Fatal编程技术网

Multithreading 乒乓球程序Java多线程

Multithreading 乒乓球程序Java多线程,multithreading,Multithreading,我试图学习多线程的基本概念 为什么我的乒乓程序只打印Ping0&Pong0,为什么notify()不启动处于等待状态的乒乓线程 公共类乒乓球实现可运行{ 字符串字 public PingPong(String word) { this.word = word; } public void run() { synchronized (this) { for (int i = 0; i < 10; i++) { System.out.

我试图学习多线程的基本概念

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

公共类乒乓球实现可运行{ 字符串字

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

  }

}
我尝试删除wait(),它会打印乒乓球直到循环结束。但这能保证它会按顺序打印吗

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

  • 如果您看到jstack,您可以看到线程0和线程1正在等待不同的锁。这是因为p1和p2是不同的对象,所以当您使用
    synchronized(this)
    时,它们不会竞争同一个锁,因此通知这种方式不起作用。请尝试使用另一个对象作为锁
  • wait需要在notify之后运行。当两个线程都进入等待状态时,没有其他线程可以通知它们
  • 请尝试以下代码:

    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();
    
    }
    
    字符串字;
    对象a;
    公共乒乓球(字符串、对象a){
    这个单词=单词;
    这个a=a;
    }
    公开募捐{
    已同步(a){
    对于(int i=0;i<10;i++){
    系统输出打印项次(word+i);
    试一试{
    a、 notifyAll();
    a、 等待();
    }捕获(例外e){
    System.out.println(e.getMessage());
    }
    }
    }
    }
    公共静态void main(字符串[]args)引发InterruptedException{
    对象a=新对象();
    Runnable p1=新乒乓球(“ping”,a);
    螺纹t1=新螺纹(p1);
    t1.start();
    Runnable p2=新乒乓球(“乒乓球”,a);
    螺纹t2=新螺纹(p2);
    t2.start();
    }
    
  • 如果您看到jstack,您可以看到线程0和线程1正在等待不同的锁。这是因为p1和p2是不同的对象,所以当您使用
    synchronized(this)
    时,它们不会竞争同一个锁,因此通知这种方式不起作用。请尝试使用另一个对象作为锁
  • wait需要在notify之后运行。当两个线程都进入等待状态时,没有其他线程可以通知它们
  • 请尝试以下代码:

    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();
    
    }
    
    字符串字;
    对象a;
    公共乒乓球(字符串、对象a){
    这个单词=单词;
    这个a=a;
    }
    公开募捐{
    已同步(a){
    对于(int i=0;i<10;i++){
    系统输出打印项次(word+i);
    试一试{
    a、 notifyAll();
    a、 等待();
    }捕获(例外e){
    System.out.println(e.getMessage());
    }
    }
    }
    }
    公共静态void main(字符串[]args)引发InterruptedException{
    对象a=新对象();
    Runnable p1=新乒乓球(“ping”,a);
    螺纹t1=新螺纹(p1);
    t1.start();
    Runnable p2=新乒乓球(“乒乓球”,a);
    螺纹t2=新螺纹(p2);
    t2.start();
    }
    
    下面是一个使用线程池执行器的类似解决方案:

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

    下面是一个使用线程池执行器的类似解决方案:

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

    以下解决方案基于:

    • 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);
              }
          }
      }
      
      公共类测试{
      公共静态void main(字符串[]args){
      SynchronousQueue=新的SynchronousQueue();
      线程ping=新线程(新任务(队列,“ping”、“ping”);
      ping.setName(“ping线程”);
      ping.start();
      线程pong=新线程(新任务(队列,“pong”、“ping”);
      pong.setName(“pong线程”);
      pong.start();
      }
      私有静态类任务实现可运行{
      私有同步队列;
      私有字符串命令;
      私有字符串步;
      任务(SynchronousQueue队列、字符串命令、字符串步骤){
      this.queue=队列;
      this.command=命令;
      这个步骤=步骤;
      }
      @凌驾
      公开募捐{
      试一试{
      if(命令等于(步骤)){
      DoCommand和Wait();
      }否则{
      waitAndDoCommandRepeatedly();
      }
      }捕捉(中断异常e){
      Thread.currentThread().interrupt();
      }
      }
      private void doCommandAndWaitRepeatedly()引发InterruptedException{
      while(true){
      queue.offer(命令,1,时间单位,秒);
      睡眠(500);
      System.out.println(Thread.currentThread().getName()+“:”+queue.poll(1,TimeUnit.SECONDS));
      }
      }
      private void waitAndDoCommandRepeatedly()抛出InterruptedException{
      while(true){
      System.out.println(Thread.currentThread().getName()+“:”+queue.poll(1,TimeUnit.SECONDS));
      睡眠(500);
      queue.offer(命令,1,时间单位,秒);
      }
      }
      }
      
      }


      • 以下解决方案基于:

        • 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);
                  }
              }
          }
          
          公共类测试{
          公共静态void main(字符串[]args){
          SynchronousQueue=新的SynchronousQueue();
          线程ping=新线程(新任务(队列,“ping”、“ping”);
          ping.setName(“ping线程”);
          ping.start();
          线程pong=新线程(新任务(队列,“pong”、“ping”);
          pong.setName(“pong线程”);
          pong.start();
          }
          私有静态类任务实现可运行{
          私有同步队列;
          私有字符串命令;
          私有字符串步;
          任务(SynchronousQueue队列、字符串命令、字符串步骤){
          this.queue=队列;
          this.command=命令;
          这个步骤=步骤;
          }
          @凌驾
          公开募捐{
          试一试{
          if(命令等于(步骤)){
          DoCommand和Wait();
          }否则{
          waitAndDoCommandRepeatedly();
          }
          }捕捉(中断异常e){
          Thread.currentThread().interrupt();
          }
          }
          private void doCommandAndWaitRepeatedly()引发InterruptedException{
          while(true){
          queue.offer(命令,1,时间单位,秒);
          睡眠(500);
          System.out.println(Thread.currentThread().getNam