我使用下面的类以同步方式或异步方式使用socket将数据发送到我们的消息队列。如下所示。
截至目前,我正在复制下面课程中的大量代码。我有5个方法用于同步或异步发送数据,我相信可能有更好的方法来重写这些方法。
public class SendRecord {
private final ScheduledExecutorService executorService = Executors.newScheduledThreadPool(2);
private final Cache<Long, PendingMessage> cache =
CacheBuilder
.newBuilder()
.maximumSize(2000000)
.concurrencyLevel(100).build();
private static class Holder {
private static final SendRecord INSTANCE = new SendRecord();
}
public static SendRecord getInstance() {
return Holder.INSTANCE;
}
private SendRecord() {
executorService.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
handleRetry();
}
}, 0, 1, TimeUnit.SECONDS);
}
private void handleRetry() {
List<PendingMessage> messages = new ArrayList<>(cache.asMap().values());
for (PendingMessage message : messages) {
if (message.hasExpired()) {
if (message.shouldRetry()) {
message.markResent();
doSendAsync(message);
} else {
cache.invalidate(message.getAddress());
}
}
}
}
// called by multiple threads concurrently
public boolean sendAsync(final long address, final byte[] encodedRecords) {
PendingMessage m = new PendingMessage(address, encodedRecords, true);
cache.put(address, m);
return doSendAsync(m);
}
// called by above method and also by handleRetry method
private boolean doSendAsync(final PendingMessage pendingMessage) {
Optional<SocketHolder> liveSocket = SocketManager.getInstance().getNextSocket();
ZMsg msg = new ZMsg();
msg.add(pendingMessage.getEncodedRecords());
try {
// this returns instantly
return msg.send(liveSocket.get().getSocket());
} finally {
msg.destroy();
}
}
// called by send method below
private boolean doSendAsync(final PendingMessage pendingMessage, final Socket socket) {
ZMsg msg = new ZMsg();
msg.add(pendingMessage.getEncodedRecords());
try {
// this returns instantly
return msg.send(socket);
} finally {
msg.destroy();
}
}
// called by multiple threads to send data synchronously without passing socket
public boolean send(final long address, final byte[] encodedRecords) {
PendingMessage m = new PendingMessage(address, encodedRecords, false);
cache.put(address, m);
try {
if (doSendAsync(m)) {
return m.waitForAck();
}
return false;
} finally {
cache.invalidate(address);
}
}
// called by a threads to send data synchronously but with socket as the parameter
public boolean send(final long address, final byte[] encodedRecords, final Socket socket) {
PendingMessage m = new PendingMessage(address, encodedRecords, false);
cache.put(address, m);
try {
if (doSendAsync(m, socket)) {
return m.waitForAck();
}
return false;
} finally {
cache.invalidate(address);
}
}
public void handleAckReceived(final long address) {
PendingMessage record = cache.getIfPresent(address);
if (record != null) {
record.ackReceived();
cache.invalidate(address);
}
}
}
有没有更好的方法来重写上述方法?
答案 0 :(得分:2)
乍一看,您可以使用&#34;提取方法&#34;重构几次。
此代码重复:
ZMsg msg = new ZMsg();
msg.add(pendingMessage.getEncodedRecords());
try {
// this returns instantly
return msg.send(liveSocket.get().getSocket());
} finally {
msg.destroy();
}
所以从中创建类似private void sendMsg()的东西。 此代码也重复
PendingMessage m = new PendingMessage(address, encodedRecords, false);
cache.put(address, m);
try {
if (doSendAsync(m, socket)) {
return m.waitForAck();
}
return false;
} finally {
cache.invalidate(address);
}
所以从中做出另一种方法。
总的来说,这是一本关于重构的经典优秀书籍https://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672
答案 1 :(得分:-1)
有两种方法可以减少java代码。
您可以在java项目中使用单个kotlin文件或转换整个项目。 Eclipse和Android Studio可以将整个项目从Java转换为Kotlin。
您可以在Kotlin类中使用Java类,反之亦然。
在Kotlin中,您可以使用默认参数。
fun doSendAsync(pendingMessage: PendingMessage, socket: Socket = SocketManager.getInstance().getNextSocket().get().getSocket())
如果传递了套接字,则会使用它。否则将使用SocketManager.getInstance()。getNextSocket()。get()。getSocket()。
这是
的方法声明 private boolean doSendAsync(final PendingMessage pendingMessage, final Socket socket)
和
private boolean doSendAsync(final PendingMessage pendingMessage)
如果要使用Java,请执行以下操作。
private boolean doSendAsync(final PendingMessage pendingMessage) {
return doSendAsync(pendingMessage), SocketManager.getInstance().getNextSocket().get().getSocket());
}