我试图测试我的聊天客户端系统是用客户端线程制作的,每个线程都有一个套接字,它连接到服务器。现在我正在尝试运行等待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();
}
}
}
答案 0 :(得分:1)
通过空循环进行同步不是一个好习惯:
while (server.getChatroomSize("USA") != NUMBER_OF_SOCKETS) {
}
...为此会使CPU接近100%,导致其余线程出现阻塞。
理想情况下,线程之间的同步应该通过 wait-notify 范例完成。哦,好的:我看到你在这里同步两个不同的程序:测试程序正在等待主程序中的某个条件为真。好吧,我建议你完成那个空循环,这样它就不会独占CPU时间。至少,像这样:
`while (server.getChatroomSize("USA") != NUMBER_OF_SOCKETS) {
Thread.sleep(10);
Thread.yield();
}`
通过try-with-resources指令尽早关闭流也是一种很好的做法:
try(PrintWriter stream = ...)
{
...
}
(同上读者。)
请检查您的代码,以简化不必要的复杂表达式,如下所示:
2 + 2 * (NUMBER_OF_SOCKETS - 1);
我没有清楚地看到这种情况的意图:
for (int j = 0; j < totalMessages; j++)
通过以前的程序逻辑,我理解每个插槽只写一条消息。但是在这个循环中,totalMessages==2
,为什么要在每个套接字上预期两条消息?