我一直在尝试使用通过我自己的系统上的套接字连接的客户端 - 服务器对来解决消费者 - 生产者问题。到目前为止,它一直进展顺利,但只剩下一个问题。超时后我的服务器程序不会退出,而客户端会这样做。
我得到的客户端代码如下所示:
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变量(我的退出标志);因为它在客户端内。我也确定,在最后的适当点,将done变量设置为true。
有关如何解决此错误的任何想法?
答案 0 :(得分:0)
实际上我设法将Manipulator的声明更改为另一个线程直接调用的内容。那个行为解决了我自己的问题。很抱歉给那些已经尝试解决问题的人带来不便。有兴趣的人试图学习这个复杂问题的代码。