为什么在超时后我的java服务器程序退出?

时间:2014-11-30 01:15:28

标签: java multithreading sockets

我一直在尝试使用通过我自己的系统上的套接字连接的客户端 - 服务器对来解决消费者 - 生产者问题。到目前为止,它一直进展顺利,但只剩下一个问题。超时后我的服务器程序不会退出,而客户端会这样做。

我得到的客户端代码如下所示:

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。

有关如何解决此错误的任何想法?

1 个答案:

答案 0 :(得分:0)

实际上我设法将Manipulator的声明更改为另一个线程直接调用的内容。那个行为解决了我自己的问题。很抱歉给那些已经尝试解决问题的人带来不便。有兴趣的人试图学习这个复杂问题的代码。