(第一种情况) public void sendMessage(){
   try {
   System.out.println(str+"!first");
dos.writeUTF(str);
} catch (IOException e) {
e.printStackTrace();
}
 }
 
public void run() {
try{
//接受客户端发送过来的信息,并读取信息
  while(connect){
str=dis.readUTF(); 
 
//把信息发送给各个客户端
for(int i=0;i<clients.size();i++){
  //实例化各个客户端
 Client c1=clients.get(i);
 c1.sendMessage();
}
  }
(第二种情况) public void sendMessage(String str){
   try {
   System.out.println(str+"!first");
dos.writeUTF(str);
} catch (IOException e) {
e.printStackTrace();
}
 }
 
public void run() {
try{
//接受客户端发送过来的信息,并读取信息
  while(connect){
str=dis.readUTF(); 
 
//把信息发送给各个客户端
for(int i=0;i<clients.size();i++){
  //实例化各个客户端
 Client c1=clients.get(i);
 c1.sendMessage(str);
}
  }     
       (问题:为什么从客户端输入时。。输出的结果不同。是什么原理呢?)

解决方案 »

  1.   

    不明白LZ想说什么?
    线程的执行是随机的,如果是多线程的话
    从str=dis.readUTF(); 到c1.sendMessage(str);(或c1.sendMessage();)
    不能保证str的一致,因为第一个线程刚要执行c1.sendMessage(str);的时候,另一个线程可能会执行str=dis.readUTF(); 这样,str就被改变了
      

  2.   

    只有上帝知道下一时刻cpu会执行哪一个线程
      

  3.   

      服务器端的代码如下:
    import java.io.*;
    import java.net.*;
    import java.util.*;public class ChatServer01 { boolean connect=false;
    ServerSocket ss=null;
    List<Client> clients=new ArrayList<Client>();

    public static void main(String[] args) {
                new ChatServer01();
    }

    //定义构造函数 
    public ChatServer01(){
    Socket s=null;
    DataInputStream dis=null;
      try {
     ss=new ServerSocket(8888);

    //等待要连接的客户端
    while(true){
      s=ss.accept();
      connect=true;
      Client c=new Client(s);   
      new Thread(c).start();
      //把连接进来的客户端添加到容器ArrayList中
      clients.add(c);
      System.out.println("a client connected!");
                     }
            }catch(Exception e){
              e.printStackTrace();
            }
            finally{
             try {
    ss.close();
    } catch (IOException e) {
    e.printStackTrace();
    }
            }
    }
        
    //定义内部线程类
    class Client implements Runnable{
            Socket s=null;
            DataInputStream dis=null;
            DataOutputStream dos=null;
            String str=null;
     public Client(Socket s){
       this.s=s;
       try {
    dis=new DataInputStream(s.getInputStream());
    dos=new DataOutputStream(s.getOutputStream());
    } catch (IOException e) {
    e.printStackTrace();
    }  
     }
     
     public void sendMessage(){
       try {
       System.out.println(str+"!first");
    dos.writeUTF(str);
    } catch (IOException e) {
    e.printStackTrace();
    }
     }
     
    public void run() {
    try{
    //接受客户端发送过来的信息,并读取信息
      while(connect){
    str=dis.readUTF(); 
     
    //把信息发送给各个客户端
    for(int i=0;i<clients.size();i++){
      //实例化各个客户端
     Client c1=clients.get(i);
     c1.sendMessage();
    }
      }  
    } catch (IOException e) {
    System.out.println("error");
    }finally{
      try{
        if(dis!=null) dis.close();
        if(dos!=null) dos.close();
        if(s!=null) s.close();     
      }catch(Exception e){
       e.printStackTrace();
      }
    }
      
    }
      }
    }
     
      

  4.   

    第1个情况下,str作为的是全局变量,即意味着任何一个请求都可以改变该变量的内容,这个道理就和你平时写servlet不是一样的吗?保证线程安全最简单有效的办法就是使资源不是共享的
      

  5.   

    两种写法没有本质区别,只是调用sendMessage的时候有参数和没参数的区别,但是这个参数是来自成员变量的str,所以多线程的时候不能保证同步,你的第二种方法能得到正确结果,那也是偶然的,因为两种方法的问题都是同一样的,只是因为线程的随机性,导致你第二种方法偶尔正确。其中原因我已经在上面分析了,LZ好好理解一下。
      

  6.   

       如果把String s=null;这个全局变量。。放到局部变量呢?
    如:
    public void run() {
    try{
    //接受客户端发送过来的信息,并读取信息
    while(connect){
     String str=dis.readUTF();  
      
    //把信息发送给各个客户端
    for(int i=0;i<clients.size();i++){
    //实例化各个客户端
    Client c1=clients.get(i);
    c1.sendMessage(str); 
    }

    效果怎么样?
      

  7.   

    我想请教一下:为什么第2种sendMessage(String str)得到正确结果,您说是偶然的呢,str已经不是全局变量了吧?
      

  8.   

    放到局部变量是没什么问题,即传输数据没什么问题,不过还是有点
    也就是说
    for(int i=0;i<clients.size();i++){
    //实例化各个客户端
    Client c1=clients.get(i);
    c1.sendMessage(str);  //这里有传输先后的影响,具体LZ自己体会吧