我目前正在尝试实现一个与机器通信的应用程序,它应该基本上如下工作:
所以,我们想到有一个线程来做发送,另一个做接收,因为我们有一个api来注册一个类来接收来自机器的消息(只是通过实现一个接口),以及向机器发送消息的方法不属于阻塞类型,因此需要等待机器响应的方法,以便程序可以在响应到达后决定做什么。
因此,我们需要以某种方式同步这两个线程,因为它可以确定它们将交换多少消息,这使我们尝试使用CyclicBarrier。这是用于测试CyclicBarrier是否可以帮助我们解决此问题的代码(程序实际上不使用套接字与机器通信,这仅用于测试屏障):
import java.io.*;
import java.net.*;
import java.util.concurrent.*;
public class BlockingTest{
private CyclicBarrier barrier;
class Receiver implements Runnable{
@Override public void run(){
try{
ServerSocket ss = new ServerSocket(8080);
while(!barrier.isBroken()){
System.out.println("Waiting message...");
Socket response = ss.accept();
BufferedReader br = new BufferedReader(new InputStreamReader(
response.getInputStream()));
System.out.printf("Received: %s\n", br.readLine());
barrier.await();
}
}catch(InterruptedException | BrokenBarrierException |
IOException ex){
System.err.println(ex.getMessage());
}
}
}
public BlockingTest(){
this.barrier = new CyclicBarrier(2, new Runnable(){
@Override public void run(){
System.out.println("done.");
}
});
new Thread(new Receiver()).start();
try{
Socket sender = new Socket("localhost", 8080);
PrintWriter pw = new PrintWriter(sender.getOutputStream(), true);
for(int i = 0; i < 3; i++){
System.out.println("Sending message:");
pw.println("Message!");
this.barrier.await();
}
}catch(InterruptedException | BrokenBarrierException | IOException ex){
System.err.println(ex.getMessage());
}
}
public static void main(String[] arg){
new BlockingTest();
}
}
如果我们只发送一条消息(BlockingTest()构造函数中的块没有,只发送消息),此代码按预期工作,但添加for块后,它不能按预期工作。它只在第一次工作,然后挂起:
Waiting message...
Sending message:
Received: Message!
done.
Waiting message...
Sending message:
问题是:
如何使屏障可重复使用?这是自动的还是有的 手工完成?
由于插座(或屏障代码)错过了某些内容,程序是否悬空?
答案 0 :(得分:0)
它挂起的原因是你打开一个到服务器的连接并继续向它发送数据,但是在接收端,你丢弃了第一个连接,并开始等待下一个连接发生。
每次发送数据时都可以从发件人创建新连接。代码块
Socket sender = new Socket("localhost", 8080);
PrintWriter pw = new PrintWriter(sender.getOutputStream(), true);
必须在for循环中移动。 (当然,注意释放所有资源)
OR,
修复接收方从第一个连接读取数据,而不是等待第二个数据包的新连接。