套接字不打印数据

时间:2018-04-07 19:05:46

标签: java multithreading sockets

我试图测试我的聊天客户端系统是用客户端线程制作的,每个线程都有一个套接字,它连接到服务器。现在我正在尝试运行等待3个客户端线程的测试通过选择房间连接(房间的名称是美国),然后互相发送消息,但是当我运行测试2场景发生时:

1.所有3个线程开始,但是3个中有2个打印出他们收到的内容,之后没有任何反应,测试卡住,@ AfterSuite甚至无法运行

2.所有3个线程开始2个中的2个打印他们收到的东西,第三个线程不打印任何东西但是新的3个线程被启动(3个新的插槽被制作),最后所有6个被关闭< / p>

这不是我期望的两种情况下的行为我期望所有3个打印他们收到的东西和@AfterSuite成功运行,代码在我的主电脑上工作但现在我在不同而且它没有&#39 ; t似乎表现得像预期的那样,我无法弄清楚为什么,这里是代码:

public class NotUniqueMessagesTest {
final int NUMBER_OF_SOCKETS = 3;
Server server = new Server();

List<Socket> allsockets = new ArrayList<>();

private final CyclicBarrier barrier = new CyclicBarrier(NUMBER_OF_SOCKETS);
Thread t = new Thread(new Runnable() {

    @Override
    public void run() {
        server.start();

    }
});

@BeforeSuite
public void startServer() {

    t.start();
    System.out.println("System out println" + server.getSocket());

    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

@AfterSuite
public void stopServer() {

    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }

    server.stop();
}

@Test
public void testMessagesReceived() throws IOException {

    System.out.println(server.getChatroomSize("Bulgaria"));

    for (int i = 0; i < NUMBER_OF_SOCKETS; i++) {

        Runnable r = new Runnable() {

            @Override
            public void run() {

                try {
                    barrier.await();
                } catch (InterruptedException | BrokenBarrierException e1) {
                    e1.printStackTrace();
                }

                try {
                    Socket socket = new Socket("127.0.0.1", 3000);
                    allsockets.add(socket);
                    final PrintWriter stream = new PrintWriter(socket.getOutputStream(), true);

                    stream.println("USA");
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }

            }

        };

        new Thread(r).start();
    }

    while (server.getChatroomSize("USA") != NUMBER_OF_SOCKETS) {

    }

    System.out.println("FINISHED WAITING ALL CLIENTS HAVE COME");
    for (int i = 0; i < NUMBER_OF_SOCKETS; i++) {
        final PrintWriter stream = new PrintWriter(allsockets.get(i).getOutputStream(), true);

        stream.println("All say what I say");
    }

    int totalMessages = 2 + 2 * (NUMBER_OF_SOCKETS - 1);

    for (int i = 0; i < NUMBER_OF_SOCKETS; i++) {
        final BufferedReader reader = new BufferedReader(new InputStreamReader(allsockets.get(i).getInputStream()));

        for (int j = 0; j < totalMessages; j++) {
            String line = reader.readLine();
            System.out.println(line);

        }

        System.out.println();

    }
}

}

1 个答案:

答案 0 :(得分:1)

  1. 通过空循环进行同步不是一个好习惯:

    while (server.getChatroomSize("USA") != NUMBER_OF_SOCKETS) { }

  2. ...为此会使CPU接近100%,导致其余线程出现阻塞。

    理想情况下,线程之间的同步应该通过 wait-notify 范例完成。哦,好的:我看到你在这里同步两个不同的程序:测试程序正在等待主程序中的某个条件为真。好吧,我建议你完成那个空循环,这样它就不会独占CPU时间。至少,像这样:

    `while (server.getChatroomSize("USA") != NUMBER_OF_SOCKETS) {
        Thread.sleep(10);
        Thread.yield();
    }`
    
    1. 通过try-with-resources指令尽早关闭流也是一种很好的做法:

      try(PrintWriter stream = ...) { ... }

      (同上读者。)

    2. 请检查您的代码,以简化不必要的复杂表达式,如下所示:

      2 + 2 * (NUMBER_OF_SOCKETS - 1);

    3. 我没有清楚地看到这种情况的意图:

      for (int j = 0; j < totalMessages; j++)

    4. 通过以前的程序逻辑,我理解每个插槽只写一条消息。但是在这个循环中,totalMessages==2,为什么要在每个套接字上预期两条消息?