我正在修改Java服务器软件。整个应用程序是单线程的。我的更改之一需要花费很多时间,因此我决定异步执行此操作以避免冻结主线程。
这是原始代码的示例(不是真实代码,仅是示例):
public class Packet {
private final byte[] data = new byte[1024];
public void setData(int index, byte data) {
this.data[index] = data;
}
public byte getData(int index) {
return data[index];
}
public void sendPacket(ClientConnection clientConnection) {
clientConnection.sendPacket(data);
}
}
当前,这是我的代码(请看注释):
public class Packet {
private final byte[] data = new byte[1024];
public void setData(int index, byte data) {
synchronized (this) {
this.data[index] = data;
}
}
public byte getData(int index) {
return data[index];
}
public void sendPacket(final ClientConnection clientConnection) {
//This state of data should be sent
new Thread(new Runnable() {
@Override
public void run() {
//The thread is now running
//The main-thread can move on
//The main-thread can also modify data now because we are not inside the synchronized block
//But it should not because the state of data when the method sendPacket was called should be sent
synchronized (Packet.this) {
thisTakesMuchTime(data);
clientConnection.sendPacket(data);
}
}
}).start();
}
}
我实际上正在寻找的是这样的:
public class Packet {
private final byte[] data = new byte[1024];
public void setData(int index, byte data) {
//wait for unlock
this.data[index] = data;
}
public byte getData(int index) {
return data[index];
}
public void sendPacket(final ClientConnection clientConnection) {
//lock
new Thread(new Runnable() {
@Override
public void run() {
thisTakesMuchTime(data);
clientConnection.sendPacket(data);
//unlock
}
}).start();
}
}
问题:在Java中,这种锁的最佳实现是什么?我是否应该自己使用
AtomicInteger
做到这一点。编辑:看看我对我当前的实现的答案。
最佳答案
您可以复制数据并发送副本,以避免并发。
public class Packet {
private final byte[] data = new byte[1024];
public void setData(final int index, final byte data) {
this.data[index] = data;
}
public byte getData(final int index) {
return data[index];
}
public void sendPacket(final ClientConnection clientConnection) {
byte[] dataToSend = new byte[1024];
System.arraycopy(data, 0, dataToSend, 0, 1024);
new Thread(new Runnable() {
@Override public void run() {
clientConnection.sendPacket(dataToSend);
}
}).start();
}
}
使用
CopyOnWriteArrayList
类似于下面的代码,它还避免了并发但效率不高(假设您将比setData
调用sendPacket
的频率更高):public class Packet {
private byte[] data = new byte[1024];
public void setData(final int index, final byte data) {
byte[] newData = new byte[1024];
System.arraycopy(data, 0, newData, 0, 1024);
newData[index] = data;
this.data = newData;
}
public byte getData(final int index) {
return data[index];
}
public void sendPacket(final ClientConnection clientConnection) {
new Thread(new Runnable() {
@Override public void run() {
clientConnection.sendPacket(data);
}
}).start();
}
}