不久后服务器和客户会死掉 ,是因为,所以的客户都卡在了  in.readLine() 上 

解决方案 »

  1.   

    1:userList.add(client);运行时还不能保证client.out被初始化。应该把这条语句放在client线程里out被初始化后
    2:多线程的资源访问同步。涉及userlist的操作、broadcast都需要线程同步。你对synchronized的使用方法还没有理解。在run上和sendToChat上使用的synchronized都是不正确的,不能起到你想要的效果。3:客户端收到的消息数要比发送的消息数要多得多,你在同一个线程里发一次收一次,显然是不正确的。这个题目确实是多线程程序的典型例子,你改好了再贴上了。
      

  2.   

    首先感谢[taolei(实在无聊) ]的敬业精神,你是真心为我解答的,看清了程序中的许多问题,万分感谢,凭着这种精神和心细密,一定是大有前途的!
    按照你所说程序确实有了质的改观,但有人建议我做成双线程,一个线程管收控制out,一个管发控制in,不知你对此有什么看法?下面是我改好的程序,可能还是不尽如人意的地方,但已经可以用了。server.java
    import java.net.*;
    import java.util.*;
    import java.io.*;
    public class Server extends Thread{
        private ServerSocket server;
        private Socket socket;
        private boolean isRun;
        private LinkedList userList;    public Server(int port) {
            this.userList=new LinkedList();
            try {
                server = new ServerSocket(port);        } catch (IOException ex) {
                System.out.println("-1:"+ex);
            }
        }    public void run(){
            int i = 0;
            isRun = true;
            while (isRun) {
                try {
                    this.socket = server.accept();
                } catch (IOException ex) {
                    System.out.println("---1:"+ex);
                }
                CliThread client = new CliThread(userList, socket);
                client.start();
                client.setName("_user" + i);
                System.out.println(i+"---------------------------"+client.getName()+" success!");
                i++;
            }    }
        
           public static void main(String args[]) {
            Server aa = new Server(3001);
            aa.start();
        }
    }
    CliThread.java/**
     * <p>Title: </p>
     *
     * <p>Description: </p>
     *
     * <p>Copyright: Copyright (c) 2004</p>
     *
     * <p>Company: </p>
     *
     * @author not attributable
     * @version 1.0
     */import java.io.*;
    import java.net.*;
    import java.util.*;public class CliThread extends Thread{
        private BufferedReader in;
        private PrintWriter out;
        private Socket socket;
        private LinkedList userList;    public CliThread(LinkedList userList,Socket socket) {
            this.userList=userList;
            this.socket=socket;
        }    public void run(){
            try {
                in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                out=new PrintWriter(socket.getOutputStream());
                
                synchronized(userList){
    userList.add(out);
    }

                String data=null;
                int i=0;
                while((data=in.readLine())!=null){
                    System.out.println(i+"---------------"+data);
                   broadcast(data);
                    i++;
                }
            } catch (IOException ex) {
                System.out.println("2:"+ex);
            }
        }
        
        public void send(String msg){
          out.println(msg);
            out.flush();
       }
       
       public synchronized void broadcast(String msg){
    for(int j=0;j<userList.size();j++){
           PrintWriter client=(PrintWriter)userList.get(j);
                out.println(msg);
            out.flush();
    }
    }
    }Client.java
    /**
     * <p>Title: </p>
     *
     * <p>Description: </p>
     *
     * <p>Copyright: Copyright (c) 2004</p>
     *
     * <p>Company: </p>
     *
     * @author not attributable
     * @version 1.0
     */import java.net.*;
    import java.io.*;
    import java.sql.*;public class Client  extends Thread {
      private boolean running;
      private PrintWriter out;
      private BufferedReader in;
      private Socket socket;
      private String server = "localhost";
      private int port;
      private String name;  public Client(String name,int port) {
        this.name=name;
        this.port=port;
        connect();
      }  public void run() {    char charBuffer[] = new char[1];
        sendToChat("<login CN='"+this.name+"' x='111' y='-34' />");
        running = true;    while (running) {
          int ran=(int)(Math.round(Math.random()*6)+1);
          int x=(int)(Math.round(Math.random()*500));
          int y=(int)(Math.round(Math.random()*120));
          switch(ran){
            case 1:sendToChat("<face ID='"+this.name+"' value='3' />");break;
            case 2:sendToChat("<face ID='"+this.name+"' value='3' />");break;
            case 3:sendToChat("<face ID='"+this.name+"' value='3' />");break;
            case 4:sendToChat("<face ID='"+this.name+"' value='3' />");break;
            case 5:sendToChat("<face ID='"+this.name+"' value='3' />");break;
            case 6:sendToChat("<face ID='"+this.name+"' value='3' />");break;
            default:sendToChat("<face ID='"+this.name+"' value='3' />");
          }
          
          try {
           while(in.ready()){
           System.out.println(in.readLine());
           }
            this.sleep(20);
          }
          catch (Exception ex) {
            System.out.println(ex);
          }
         
        }
      }
      private int connect() {
        try {
          socket = new Socket(server, port);
          in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
          out = new PrintWriter(socket.getOutputStream());    }
        catch (UnknownHostException ex) {
          return 1;
        }
        catch (IOException ex) {
          return 2;
        }
        return 0;
      }   public synchronized void sendToChat(String msg) {
         out.println(msg);     //out.write(msg);
         out.flush();  }  private void shutdown() throws IOException {
        in.close();
        out.close();
        socket.close();
      }  public static void main(String args[]) {    int limit=40;
        for(int i=0;i<limit;i++){
          Client cc=new Client("aabbcc"+i,Integer.parseInt(args[0]));
          cc.start();
          try {
              Thread.sleep(500);
          }
          catch (InterruptedException ex) {
          }
        }
        System.out.println("---------------------finish!");
      }
    }
      

  3.   

    server端还有点问题:
    前面用的synchronized(userlist),那么broadcast也应该用synchronized(userlist)当一个客户端连接断开后,server端并没有把这个连接从userlist里删除,同时你的broadcast里并未catch任何异常,所有其他的连接同时也会收到影响。我也是建议客户端用两个线程,一个发送,一个接收。
      

  4.   

    如果是多个客户,就应用多线程,否则到readLine()时程序会等待,他也就不会处理其它用户的工作,相当于死了。