Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/334.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
Java 如何使用线程实现读写器程序?_Java_Loops_Java Threads_Reader_Writer - Fatal编程技术网

Java 如何使用线程实现读写器程序?

Java 如何使用线程实现读写器程序?,java,loops,java-threads,reader,writer,Java,Loops,Java Threads,Reader,Writer,我对读写器实现有问题。我应该编写一个Reader类,从控制台获取一个字符串并将其添加到队列中;编写器类使用线程从同一队列中删除该字符串并将其输出到控制台中。我只为一个字符串编写了我的程序(键入一个字符串,它会通过队列输出该字符串),这非常有效。现在,我正在努力使其能够输入多个字符串,按Enter键,然后读取器将其添加到队列中,然后写入器将其显示。如果键入了字符串quit,则两个线程都必须停止,程序应该结束 我的读者想法如下: Scanner k = new Scanner(System.in);

我对读写器实现有问题。我应该编写一个Reader类,从控制台获取一个字符串并将其添加到队列中;编写器类使用线程从同一队列中删除该字符串并将其输出到控制台中。我只为一个字符串编写了我的程序(键入一个字符串,它会通过队列输出该字符串),这非常有效。现在,我正在努力使其能够输入多个字符串,按Enter键,然后读取器将其添加到队列中,然后写入器将其显示。如果键入了字符串
quit
,则两个线程都必须停止,程序应该结束

我的读者想法如下:

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);
  }
}
public void run(){
  synchronized(q){
    while(!q.isEmpty()){
      String out = q.dequeue();
      System.out.println(out);
    }
  }
}
我的作者是这样的:

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);
  }
}
public void run(){
  synchronized(q){
    while(!q.isEmpty()){
      String out = q.dequeue();
      System.out.println(out);
    }
  }
}
我的阅读器似乎工作正常,因为我在添加到队列后内置了
Sys.out.(q.isEmpty)
。它向我显示队列已满,但Writer类没有向控制台输出任何内容。写入
quit
将停止程序,不会出现任何问题

我不认为我完全理解线程。我的主要方法只是创建
threadt1=newthread(newreader(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);
  }
}
这个同步块太大了。通常,您希望同步时间尽可能短。进进出出。同步时间越长,其他线程被阻止的时间就越长

同步时执行用户输入是不行的。其他线程不应该被阻止,因为用户的打字速度很慢

更糟糕的是,整个程序的循环都在同步块中。糟糕的读者!太贪婪了。在用户输入所有输入并键入“退出”之前,它不会放弃
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时间,在那个该死的用户慢慢啄键盘时循环数百万次。如果您检查您的系统监视器,您将看到程序的CPU使用率达到100%。不太好


解决这个问题有点超出了本问答的范围。简单的回答是让作者睡觉,直到有东西可用。

提醒我,已经有一段时间没有上课了:读写器涉及读者的读锁和作者的写锁(独占锁),对吗?我不明白你是如何通过像这样一个简单的同步块来实现这一点的。嘿,非常感谢!我很清楚,我还没有完全理解线程,但你的一句话确实让我理解了很多——“它没有放弃q锁”——我没有那样想,但我想我现在理解得更多了。至于表演,谢谢你指出,但我的课程根本没有讨论过这样的事情;我想晚些时候会有。感谢您提供有关
等待
通知
的链接-我将查看!干杯