多线程为什么我的java服务器程序在超时后不退出?
我一直在尝试使用通过我自己系统上的socket连接的客户机-服务器对来解决消费者-生产者问题。到目前为止一切都很顺利,但只剩下一个问题。我的服务器程序在超时后不会退出,而客户端会退出
我得到的客户端代码如下所示:
import java.util.*;
import java.net.*;
import java.io.*;
public class ConsumerClient {
protected static boolean done = false;
private static InetAddress host;
private static final int PORT = 4545;
private static BufferedReader inS;
private static PrintWriter outS;
private static Socket link;
static class Consumer implements Runnable {
Random random = new Random();
@Override
public void run() {
try {
while(true) {
String recieved;
try {
outS.println("1");
} catch(Exception e) {
System.out.println(e);
}
recieved = inS.readLine();
System.out.println("Recieved object: " + recieved);
if(done) {
System.out.println("Consumer done.");
outS.println("0");
return;
}
}
} catch(IOException e) {
System.out.println(e);
} catch (Exception e) {
System.out.println(e);
}
}
}
public static void main(String[] args) {
//Allows the user to control the number of consumer threads
Scanner keyboard = new Scanner(System.in);
System.out.print("Enter number of consumers: ");
int numConsumers = keyboard.nextInt();
System.out.print("Enter how long (seconds) to run: ");
int time = keyboard.nextInt();
System.out.println("Client ready! Continue when server ready.");
System.out.print("Type \"abort\" and press \"Enter\" to stop "
+ "immediately or type anything else to continue: ");
String cmd = keyboard.next();
if(!cmd.toLowerCase().equals("abort")) {
try {
System.out.println("Acquiring host...");
host = InetAddress.getLocalHost();
System.out.println("Connecting to server...");
link = new Socket(host,PORT);
System.out.println("Connection found.");
inS = new BufferedReader(new InputStreamReader(
link.getInputStream()));
outS = new PrintWriter(link.getOutputStream(),true);
} catch(UnknownHostException e) {
System.out.println(e);
System.exit(1);
} catch(IOException e) {
System.out.println(e);
}
System.out.println("Connection established: " + host + ": "
+ PORT);
Consumer c = new Consumer();
for (int i = 0; i < numConsumers; i++) {
new Thread(c).start();
System.out.println("Consumer " + (i+1) + " starts...");
}
try {
Thread.sleep(time*1000);
} catch(Exception e) {
System.out.println(e);
}
System.out.println("Time out.");
}
done = true;
System.out.println("Client shutting down.");
}
}
以下是服务器代码:
import java.util.*;
import java.io.*;
import java.util.concurrent.*;
import java.net.*;
public class ProducerServer {
private static ServerSocket servSock;
private static final int PORT = 4545;
protected static boolean done = false;
private static BufferedReader inS;
private static PrintWriter outS;
private static Socket link;
static class Producer implements Runnable {
protected BlockingQueue queue;
Random random = new Random();
Producer(BlockingQueue q) {
queue = q;
}
@Override
public void run() {
try {
while (true) {
Object justProduced = new Object();
queue.put(justProduced);
System.out.println("Object produced; List size is "
+ queue.size());
if(done) {
System.out.println("Producer done.");
return;
}
}
}
catch (InterruptedException e) {
System.out.println(e);
}
}
}
static class Manipulator implements Runnable {
protected BlockingQueue queue;
Manipulator(BlockingQueue q) {
queue = q;
}
@Override
public void run() {
try {
String request = inS.readLine();
while(true) {
if(request.equals("0")) {Thread.sleep(100);}
if(request.equals("1")) {
Object obj = queue.take();
int len = queue.size();
System.out.println("Object taken; list size is " + len);
System.out.println("Sending object: " + obj);
outS.println(obj);
}
request = inS.readLine();
if(done){
System.out.println("Manipulator done.");
return;
}
}
} catch(Exception e) {
System.out.println(e);
}
}
}
public static void main(String[] args) {
Scanner keyboard = new Scanner(System.in);
System.out.print("Enter number of producers: ");
int numProducers = keyboard.nextInt();
System.out.print("Enter how long (seconds) to run: ");
int time = keyboard.nextInt();
System.out.println("Server ready! Continue when client ready.");
System.out.print("Type \"abort\" and press \"Enter\" to stop "
+ "immediately or type anything else to continue: ");
String cmd = keyboard.next();
if(!cmd.toLowerCase().equals("abort")) {
try {
System.out.println("Opening port...");
servSock = new ServerSocket(PORT);
System.out.println("Awaiting client connection...");
link = servSock.accept();
System.out.println("New client found.\n");
inS = new BufferedReader(new InputStreamReader(
link.getInputStream()));
outS = new PrintWriter(link.getOutputStream(), true);
} catch(IOException e) {
System.out.println(e);
System.exit(1);
}
System.out.println("Connection established on port: " + PORT);
BlockingQueue myQueue = new ArrayBlockingQueue(10);
for (int i = 0; i < numProducers; i++)
new Thread(new Producer(myQueue)).start();
Manipulator m = new Manipulator(myQueue);
m.run();
try {
Thread.sleep(time*1000);
} catch(Exception e) {
System.out.println(e);
}
System.out.println("Time out.");
}
done = true;
System.out.println("Server shutting down.");
}
}
我说这些程序基本上已经在运行了,但我只是想在我提交之前问一下最后一个错误
我已经检查了done变量(我的exit标志)是否可以被服务器程序中的所有线程访问;因为它在客户机中。我还确保了done变量在main中接近末尾的适当点设置为true
关于如何解决这个错误有什么想法吗
# 1 楼答案
实际上,我成功地将操纵器的声明更改为由另一个线程直接调用的内容。那件事本身就解决了我的问题。很抱歉给那些已经试图解决我的问题的人带来不便。代码是为试图了解这个复杂问题的相关方准备的