账号密码登录
微信安全登录
微信扫描二维码登录

登录后绑定QQ、微信即可实现信息互通

手机验证码登录
找回密码返回
邮箱找回 手机找回
注册账号返回
其他登录方式
分享
  • 收藏
    X
    java多线程生产消费打印输出倒顺序情况的原因
    95
    0
    问题如下,一段简单的代码:public class testPC2 { public static void main(String[] args) { TV tv=new TV(); new Publish(tv).start(); new Audience(tv).start(); }}class TV { String name; boolean flag = true; public synchronized void play(String name) { if(!flag){ try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } this.name=name; this.flag=!this.flag; this.notifyAll(); } public synchronized String watch() { if(flag){ try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } this.flag=!this.flag; this.notifyAll(); return this.name; }}class Publish extends Thread { TV tv; public Publish(TV tv) { this.tv = tv; } @Override public void run() { String str; for (int i = 0; i < 20; i++) { if (i % 2 == 0) { str = "快乐大本营"; } else { str = "抖音:记录美好生活"; } tv.play(str+(i+1)); System.out.println("生产了"+tv.name); } }}class Audience extends Thread { TV tv; public Audience(TV tv) { this.tv = tv; } @Override public void run() { for (int i = 0; i < 20; i++) { System.out.println("消费了-->"+tv.watch()); } }}如下打印偶尔出现生产和消费倒序输出,消费方会抢线程?不知其中原因,望大佬告知。:生产了快乐大本营1消费了-->快乐大本营1消费了-->抖音:记录美好生活2生产了抖音:记录美好生活2生产了快乐大本营3消费了-->快乐大本营3消费了-->抖音:记录美好生活4生产了抖音:记录美好生活4生产了快乐大本营5消费了-->快乐大本营5生产了抖音:记录美好生活6消费了-->抖音:记录美好生活6消费了-->快乐大本营7生产了快乐大本营7生产了抖音:记录美好生活8消费了-->抖音:记录美好生活8生产了快乐大本营9消费了-->快乐大本营9生产了抖音:记录美好生活10消费了-->抖音:记录美好生活10生产了快乐大本营11消费了-->快乐大本营11生产了抖音:记录美好生活12消费了-->抖音:记录美好生活12生产了快乐大本营13消费了-->快乐大本营13消费了-->抖音:记录美好生活14生产了抖音:记录美好生活14生产了快乐大本营15消费了-->快乐大本营15生产了抖音:记录美好生活16消费了-->抖音:记录美好生活16生产了快乐大本营17消费了-->快乐大本营17消费了-->抖音:记录美好生活18生产了抖音:记录美好生活18生产了快乐大本营19消费了-->快乐大本营19生产了抖音:记录美好生活20消费了-->抖音:记录美好生活20
    0
    打赏
    收藏
    点击回答
        全部回答
    • 0
    • 傻子也疯狂 普通会员 1楼

      在Java中,多线程生产消费(Multithreaded Printing and Consumption)是指在多线程环境下,通过并发地打印输出数据并按照一定的顺序消费数据,从而实现数据的生产和消费操作。这种操作在某些场景下可以提高程序的效率和稳定性,特别是当数据的产生和消费之间存在某种关联时,如打印输出数据和读取输出数据都是从同一文件中读取的,或者打印输出数据和打印输出数据是通过定时任务异步发送的。

      以下是一些可能的原因导致Java多线程生产消费打印输出倒顺序情况的原因:

      1. 并发打印:Java提供了多线程和多进程(Process)的支持,这些支持使得我们可以同时创建多个线程或进程来打印输出数据。每个线程或进程都有自己的打印逻辑,可能会在打印过程中改变输出顺序,从而导致倒序输出。

      示例代码:

      ```java public class PrintThread implements Runnable { private String input;

         public PrintThread(String input) {
             this.input = input;
         }
      
         @Override
         public void run() {
             for (int i = 0; i < input.length(); i++) {
                 System.out.print(input.charAt(i));
             }
         }
      

      }

      public class PrintConsumer { private PrintThread printThread;

         public PrintConsumer(PrintThread printThread) {
             this.printThread = printThread;
         }
      
         public void consume() {
             printThread.run();
         }
      

      }

      public class Main { public static void main(String[] args) { PrintThread printThread1 = new PrintThread("a"); PrintThread printThread2 = new PrintThread("b"); PrintThread printThread3 = new PrintThread("c");

             PrintConsumer printConsumer = new PrintConsumer(printThread1);
             printConsumer.consume();
      
             PrintThread printThread4 = new PrintThread("d");
             printThread4.run();
      
             printConsumer.consume();
      
             PrintThread printThread5 = new PrintThread("e");
             printThread5.run();
      
             printConsumer.consume();
      
             printThread4.run();
      
             printThread5.run();
         }
      

      } ```

      在上述代码中,打印线程1先打印"a",然后打印线程2的"b",再打印线程3的"c",最后打印线程4的"d",最后打印线程5的"e"。这就使得输出数据按照从"a"到"c",再到"d",再到"e"的顺序进行消费。

      1. 数据处理顺序:如果在打印输出数据之前需要对数据进行处理,如进行数据清洗、格式化等操作,那么处理顺序可能会影响打印输出数据的顺序。如果处理顺序是先清洗数据,然后格式化数据,那么输出数据可能会按照清洗和格式化的数据顺序进行消费,从而导致倒序输出。

      示例代码:

      ```java public class PrintThread implements Runnable { private String input;

         public PrintThread(String input) {
             this.input = input;
         }
      
         @Override
         public void run() {
             // 处理数据
             System.out.println("清洗数据:");
             System.out.println(input);
      
             // 格式化数据
             System.out.println("格式化数据:");
             System.out.println(input.toUpperCase());
      
             // 打印输出数据
             System.out.println(input);
         }
      

      }

      public class PrintConsumer { private PrintThread printThread;

         public PrintConsumer(PrintThread printThread) {
             this.printThread = printThread;
         }
      
         public void consume() {
             printThread.run();
         }
      

      }

      public class Main { public static void main(String[] args) { PrintThread printThread1 = new PrintThread("a"); PrintThread printThread2 = new PrintThread("b"); PrintThread printThread3 = new PrintThread("c");

             PrintConsumer printConsumer = new PrintConsumer(printThread1);
             printConsumer.consume();
      
             PrintThread printThread4 = new PrintThread("d");
             printThread4.run();
      
             printConsumer.consume();
      
             PrintThread printThread5 = new PrintThread("e");
             printThread5.run();
      
             printThread4.run();
      
             printThread5.run();
         }
      

      } ```

      在上述代码中,输出数据的顺序可能会因为先进行清洗数据操作,然后进行格式化数据操作,最后进行打印输出数据操作,导致输出数据按照清洗和格式化的数据顺序进行消费,从而导致倒序输出。

      1. 假设数据产生和消费是异步的,比如由一个线程或者进程异步读取文件并写入到缓冲区,然后再由另一个线程或者进程异步从缓冲区读取并打印输出,那么输出数据的顺序可能会受到缓冲区大小和缓冲区中的数据数量的影响。如果缓冲区大小较小,那么输出数据可能会按照缓冲区中的数据数量从大到小的顺序进行消费,从而导致倒序输出。

      示例代码:

      ```java public class PrintThread implements Runnable { private String input;

         public PrintThread(String input) {
             this.input = input;
         }
      
         @Override
         public void run() {
             BufferedReader reader = new BufferedReader(new FileReader("data.txt"));
             BufferedReader writer = new BufferedReader(new FileReader("output.txt"));
      
             try {
                 String line;
                 while ((line = reader.readLine()) != null) {
                     // 写入缓冲区
                     writer.write(line + "\n");
      
                     // 检查缓冲区大小和缓冲区中的数据数量
                     int bufferCount = 0;
                     while ((line = writer.readLine()) != null) {
                         bufferCount++;
                         if (bufferCount > 10) {
                             break;
                         }
                     }
      
                     // 消费缓冲区中的数据
                     for (int i = 0; i < bufferCount; i++) {
                         writer.write(line + "\n");
                     }
                 } catch (IOException e) {
                     e.printStackTrace();
                 }
             } finally {
                 reader.close();
                 writer.close();
             }
         }
      

      }

      public class PrintConsumer { private PrintThread printThread;

         public PrintConsumer(PrintThread printThread) {
             this.printThread = printThread;
         }
      
         public void consume() {
             printThread.run();
         }
      

      }

      public class Main { public static void main(String[] args) { PrintThread printThread1 = new PrintThread("a"); PrintThread printThread2 = new PrintThread("b"); PrintThread printThread3 = new PrintThread("c");

             PrintConsumer printConsumer = new PrintConsumer(printThread1);
             printConsumer.consume();
      
             PrintThread printThread4 = new PrintThread("d");
             printThread4.run();
      
             printConsumer.consume();
      
             PrintThread printThread5 = new PrintThread("e");
             printThread5.run();
      
             printThread4.run();
      
             printThread5.run();
         }
      

      } ```

      在上述代码中,输出数据的顺序可能会因为缓冲区大小和缓冲区中的数据数量的影响,即当缓冲区大小较小且缓冲区中数据数量较多时,输出数据可能会按照缓冲区中的数据数量从大到小的顺序进行消费,从而导致倒序输出。

    更多回答
    扫一扫访问手机版
    • 回到顶部
    • 回到顶部