我有2个类,其中有一个用于向socket发送命令,另一个用于接收(有时用于回答命令)。
我必须要同步吗?或者这不是必要的吗?
两个类都在自己的线程中运行,socket对象作为thread.start();
这是正确的方法吗?还是我可以做一些更高效的事情?
这有可能导致错误吗? 发送部分:
public void run(){
send_chatline("roomf");
int vvv = 0;
while (this.socket.isConnected()){
try{
Thread.sleep(10000);
vvv++;
Thread.sleep(10000);
send_chatline("alive");
Thread.sleep(10000);
if (vvv == 1) {
this.socket.flush();
this.socket.send("T,-1," + this.playerid * 3);
this.socket.flush();
}
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}
但请记住! recieveFromSock类还有时会在出现特定命令时写入。
sendTosock的唯一功能是使连接保持活动状态(能够保持联机状态)。
答案 0 :(得分:1)
我必须同步吗?
没有。 SocketImpl
有自己的内部同步。您将不会惊讶地发现发送不同步但接收是。
答案 1 :(得分:1)
唯一的保证是发送一个字节,发送一次,读取一次字节。其他人可能会说同步由运行时库或底层操作系统负责。任何此类语句都依赖于运行时实现和/或依赖于操作系统(在我看来应该被忽视)。
因此,如果你有一个线程从套接字读取,并且一个线程写入套接字,你应该没有同步就好了。
如果多个线程可以写到套接字,你应该同步它们的动作,以确保从两个线程发送的输出不会交错。
如果两个线程从套接字读取,则同样适用。您应该同步读取以确保一个线程读取的数据由于读取另一个线程而没有“间隙”。
同样的问题,同样的结论:
答案 2 :(得分:1)
您不需要同步,因为在套接字上完成同步。问题是:通过套接字进行通信的两个类/线程是否存在于同一个JVM中?如果是这样,有几个更有效的选项,最简单的是BlockingQueue其中发件人类adds的命令和接收者takes。
答案 3 :(得分:0)
我对nio类也感到好奇并且它是同步的(仅限nio)。只需看看sun JVM代码中的write方法
http://www.docjar.com/html/api/sun/nio/ch/SocketChannelImpl.java.html
检查旧的I / O套接字代码但是没有显示同步,尽管有一个acquireFD和releaseFD ......但是没有sycnhronization ...这似乎是为了防止关闭,直到所有线程上的所有写入完成(就像他们假设来自多个线程的写入在每个操作系统中都没问题...但我不知道这是否正确或者它们在JVM本机代码中同步,因此开发人员知道他们可以这样做... ....我们需要一个JVM开发人员告诉我们Windows JVM,Linux JVM和mac JVM等中是否存在同步块....
private void socketWrite(byte b[], int off, int len) throws IOException {
if (len <= 0 || off < 0 || off + len > b.length) {
if (len == 0) {
return;
}
throw new ArrayIndexOutOfBoundsException();
}
FileDescriptor fd = impl.acquireFD();
try {
socketWrite0(fd, b, off, len);
} catch (SocketException se) {
if (se instanceof sun.net.ConnectionResetException) {
impl.setConnectionResetPending();
se = new SocketException("Connection reset");
}
if (impl.isClosedOrPending()) {
throw new SocketException("Socket closed");
} else {
throw se;
}
} finally {
impl.releaseFD();
}
}