当两个线程同时获取键盘输入,出现的奇怪现象是什么原因?

Code_cloud 发布于 2017/05/21 17:26
阅读 247
收藏 0

最近写了一个聊天程序,一个客户端一个服务器端。我想实现的功能是:服务端写一句话,所有的客户端都能接收到。

我的服务端有个问题就是本应该之后一个线程来获取键盘输入的,但是我写的是,有几个客户端就创建了几个线程。将错就错,我就发现在这种情况下会出现奇怪的现象。

有时候就是输入一句话之后,再输入enter键没反应,客户端并没有输出结果,得再按一次enter才行。

如下图:输入abc,点击一次enter之后没反应

再点一次enter之后

各客户端收到数据的情况如下

求大神解释这个多线程的问题。(ps:还有一个小问题是输入中文也会出现这种问题,但是我的主要问题是,输入英文也很容易出现这种现象,所以请大神测试的时候就直接输入英文吧,别用中文测试了)

 

下面贴出代码:

先贴服务端:服务端主线程

package cn.ilovessf.version2.Server;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * 加入多线程的服务端
 * Created by admin on 2017/5/18.
 */
public class Server_v1 {
    private  static ServerSocket serverSocket = null;
    //private List<ServerSocket> socketList = new LinkedList<ServerSocket>();
    public static List<Socket> socketList = Collections.synchronizedList(new ArrayList());
    public static void main(String[] args) throws IOException{

        ServerSocket serverSocket = new ServerSocket(3000);
        int i = 0;
        while(true) {
            Socket socket = serverSocket.accept();
            socketList.add(socket);
            new Thread(new Write_Thread(socket,i)).start();
            i++;
        }
    }
}

服务端写线程:

package cn.ilovessf.version2.Server;


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;

/**
 * Created by admin on 2017/5/19.
 * 向输出流中写入数据,然后发送给客户端
 */
public class Write_Thread implements Runnable{
    Socket socket = null;
    BufferedReader br = null;
    String name = null;
    public Write_Thread(Socket socket,int i){
        this.socket = socket;
         br = new BufferedReader(new InputStreamReader(System.in));
        name = "writeThread"+i;
    }

    public void run(){
        System.out.println("Server:Write_Thread 被调用");
        try {
            String line = null;
            while ((line = br.readLine())!= null ) {
                System.out.println(line);
                    //将套接字中的输出流打包
                    for (Socket s : Server_v1.socketList) {
                        PrintStream printStream = new PrintStream(s.getOutputStream());
                        printStream.println(this.name+"  "+line);
                    }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}

下面是客户端的程序:客户端主线程:

package cn.ilovessf.version2.Client;


import java.io.IOException;
import java.net.Socket;

/**
 * Created by admin on 2017/5/19.
 */
public class Client_v2 {
    public static void main(String[] args) throws IOException{
        //创建socket
        Socket socket = new Socket("127.0.0.1" , 3000);
       // new Thread(new Write_Thread(socket)).start();
        new Thread(new Read_Thread(socket)).start();
    }
}

客户端读的线程:

package cn.ilovessf.version2.Client;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;

/**
 * Created by admin on 2017/5/19.
 * 该流负责读取客户端输出的内容
 */
public class Read_Thread implements Runnable{
    Socket socket = null;
    private String name;
    BufferedReader bufferedReader = null;
    public Read_Thread(Socket socket)throws IOException{
         this.socket = socket;
         bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        this.name = "vserion2 : readThread: ";
    }

    public void run(){
        String line = null;
        try {
            while((line = bufferedReader.readLine()) != null) {
                //获取输入流
                System.out.println(this.name + line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

求大神赐教!

 

加载中
0
yysf
yysf

java.io 包里面都是阻塞试 io,读取和写入都是有锁的,两个线程同时读取一个流,当你输入的时候,可能第一个线程正在读取,但是另外一个线程抢先得到了一个锁,然后大家都阻塞了,概率性出现。

如果你开4个客户端,最坏的情况可能就是要按4下回车。

解决办法就是在读取的地方加锁,保证在同一时间,只能有一个线程读取同一个流

返回顶部
顶部