如何使用线程实现一个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() 让作者去睡觉,直到有可用的东西。
我对 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() 让作者去睡觉,直到有可用的东西。