如何使用线程实现一个Reader/Writer程序?

How to implement a Reader/Writer program using threads?

我对 Reader/Writer 实施有疑问。我应该写一个 Reader class 从控制台获取一个字符串并将其添加到队列和一个 Writer class 从同一队列中删除字符串并将其输出到控制台,使用线程。我只为一个字符串编写程序(键入一个字符串,它通过队列输出该字符串)并且运行良好。现在我正在努力做到这一点,以便我可以输入多个字符串,按 Enter 和 Reader 然后将它添加到队列中,然后 Writer 显示它。如果键入 String quit,则两个线程都必须停止并且程序应该结束。

我的 Reader 想法是这样的:

Scanner k = new Scanner(System.in);
in = k.nextLine();
if(in.equals("quit"))
  System.exit(0);

synchronized(q){
  while(!(in.equals("quit"))){
    // System.out.println(q.isEmpty());
    q.enqueue(in);
    in = k.next();
    if(in.equals("quit"))
      System.exit(0);
  }
}

我的 Writer 看起来像这样:

public void run(){
  synchronized(q){
    while(!q.isEmpty()){
      String out = q.dequeue();
      System.out.println(out);
    }
  }
}

我的 Reader 似乎工作正常,因为我在添加到队列后内置了 Sys.out.(q.isEmpty)。它向我显示队列正在填满,但 Writer class 没有任何输出到控制台。写入 quit 可以毫无问题地停止程序。

我不认为我完全理解线程。我的主要方法只是使用 Thread t1 = new Thread(new Reader(queue)); 创建线程,并为 Writer 创建相同的线程,然后启动两个线程。

synchronized(q){
  while(!(in.equals("quit"))){
    // System.out.println(q.isEmpty());
    q.enqueue(in);
    in = k.next();
    if(in.equals("quit"))
      System.exit(0);
  }
}

这个同步块太大了。通常,您希望同步的时间越短越好。进出。您同步的时间越长,其他线程被阻塞的时间就越长。

禁止在同步时执行用户输入。不应阻塞其他线程,因为用户打字速度较慢。

更糟糕的是,整个程序的循环都在同步块中。坏了reader!如此贪婪。在用户输入所有输入并键入 "quit" 之前,它不会放弃 q 锁定。只有这样它才会释放锁并让作者继续。

while(!(in.equals("quit"))){
  // System.out.println(q.isEmpty());
  synchronized(q){
    q.enqueue(in);
  }
  in = k.next();
  if(in.equals("quit"))
    System.exit(0);
}

作者有一个不同的致命缺陷。一旦队列为空,它就会退出。不过很多时候队列都是空的,不是吗?到时候作者不应该就这么死了。

一个快速的解决方法是将整个事情包装在一个无限循环中:

public void run(){
  while (true) {
    synchronized(q){
      while(!q.isEmpty()){
        String out = q.dequeue();
        System.out.println(out);
      }
    }
  }
}

它会让作者活下去。但它也会消耗 CPU 时间,循环数百万次,而该死的用户则慢慢地啄击键盘。如果您检查系统监视器,您会看到该程序的使用率飙升至 100% CPU。不太好。

解决这个问题有点超出了本问答的范围。简短的回答是使用 wait() and notify() 让作者去睡觉,直到有可用的东西。