diff --git a/README.md b/README.md index 86d8281..f1a86da 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,8 @@ **device uuid 무조건 바꾸시오.** +자바21에 추가된 virtual thread 사용하도록 바꾸는중... + ## Example ![ex](./ex.png) @@ -72,7 +74,8 @@ TalkClient client = new TalkClient(email, password, deviceName, deviceUuid, new ``` ./gradlew jar ``` -jdk 필요 +jdk21 이상 필요 + jar 파일은 build/libs 디렉터리 안에 생성됩니다. ## Usage diff --git a/src/main/java/com/github/netricecake/Main.java b/src/main/java/com/github/netricecake/Main.java index 27a3c85..f8fabf0 100644 --- a/src/main/java/com/github/netricecake/Main.java +++ b/src/main/java/com/github/netricecake/Main.java @@ -21,6 +21,10 @@ public class Main { static String deviceUuid = "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"; // 64자 랜덤 hex-string, 이것도 에시니까 무조건 다른걸로 바꾸세요. public static void main(String[] args) throws Exception { + + System.setProperty("jdk.virtualThreadScheduler.parallelism", "1"); + System.setProperty("jdk.virtualThreadScheduler.maxPoolSize", "1"); + TalkClient client = new TalkClient(email, password, deviceName, deviceUuid, new TalkHandler() { @Override public void onMessage(Message msg) { diff --git a/src/main/java/com/github/netricecake/kakao/TalkClient.java b/src/main/java/com/github/netricecake/kakao/TalkClient.java index a0a3084..1a817dd 100644 --- a/src/main/java/com/github/netricecake/kakao/TalkClient.java +++ b/src/main/java/com/github/netricecake/kakao/TalkClient.java @@ -32,8 +32,6 @@ import java.security.MessageDigest; import java.util.HashMap; import java.util.Map; import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; public class TalkClient { @@ -54,8 +52,6 @@ public class TalkClient { private CheckInIn checkInData; private LoginListIn loginListData; - private ExecutorService locoHandlerPool; - @Getter private TalkHandler talkHandler; @@ -95,7 +91,7 @@ public class TalkClient { public void onError(Exception e) { e.printStackTrace(); } - }, Executors.newFixedThreadPool(1)); + }); byte[] body = new CheckInOut(loginData.userId).toBson(); checkInSocket.connect(); LocoPacket checkinResponse = checkInSocket.writeAndRead(new LocoPacket(1000, "CHECKIN", body)); @@ -115,9 +111,7 @@ public class TalkClient { rp = ByteUtil.hexStringToByteArray("0100ffff0100"); // 이게 도대체 뭐임 } - locoHandlerPool = Executors.newFixedThreadPool(1); - - socket = new LocoSocket(checkInData.getHost(), checkInData.getPort(), new LocoSocketHandlerImpl(this), locoHandlerPool); + socket = new LocoSocket(checkInData.getHost(), checkInData.getPort(), new LocoSocketHandlerImpl(this)); socket.connect(); LoginListOut req = new LoginListOut(); req.setDuuid(deviceUuid); @@ -139,7 +133,7 @@ public class TalkClient { connected = true; - new Thread(() -> { + Thread.ofVirtual().start(() -> { try { while (socket.isAlive()) { Thread.sleep(5 * 60 * 1000); @@ -150,7 +144,7 @@ public class TalkClient { } catch (Exception e) { e.printStackTrace(); } - }).start(); + }); } public boolean sendMessage(long chatId, int type, String message, String extra) { @@ -188,7 +182,7 @@ public class TalkClient { int status = jsonObject.get("status").getAsInt(); future.complete(status); } - }, Executors.newFixedThreadPool(1)); + }); postSocket.connect(); PostOut po = new PostOut(); diff --git a/src/main/java/com/github/netricecake/loco/LocoSocektHandler.java b/src/main/java/com/github/netricecake/loco/LocoSocektHandler.java deleted file mode 100644 index 2321286..0000000 --- a/src/main/java/com/github/netricecake/loco/LocoSocektHandler.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.github.netricecake.loco; - -public class LocoSocektHandler { - - public void onPacket(LocoPacket packet) {} - - public void onConnect() {} - - public void onDisconnect() {} - - public void onError(Exception e) {} - -} diff --git a/src/main/java/com/github/netricecake/loco/LocoSocket.java b/src/main/java/com/github/netricecake/loco/LocoSocket.java index 1e61d09..3c6a726 100644 --- a/src/main/java/com/github/netricecake/loco/LocoSocket.java +++ b/src/main/java/com/github/netricecake/loco/LocoSocket.java @@ -34,19 +34,16 @@ public class LocoSocket { @Getter private boolean alive = false; - private final LocoSocketHandler locoSocektHandler; - - private final ExecutorService handlerPool; + private final LocoSocketHandler locoSocketHandler; private final Map> waitList = new HashMap<>(); private int packetIdCounter = 1000; - public LocoSocket(String ip, int port, LocoSocketHandler locoSocektHandler, ExecutorService handlerPool) { + public LocoSocket(String ip, int port, LocoSocketHandler locoSocketHandler) { this.ip = ip; this.port = port; - this.locoSocektHandler = locoSocektHandler; - this.handlerPool = handlerPool; + this.locoSocketHandler = locoSocketHandler; } public void connect() throws IOException { @@ -69,26 +66,27 @@ public class LocoSocket { alive = true; channel.writeAndFlush(cryptoManager.generateHandshakeMessage()).sync(); channel.pipeline().addLast(new SecureLayerCodec(cryptoManager)); - channel.pipeline().addLast(new LocoCodec(locoSocektHandler, handlerPool, waitList)); - handlerPool.execute(locoSocektHandler::onConnect); - new Thread() { - @Override - public void run() { - try { - channel.closeFuture().sync(); - eventLoopGroup.shutdownGracefully(); - handlerPool.execute(locoSocektHandler::onDisconnect); - alive = false; - } catch (Exception e) { - handlerPool.execute(() -> { - locoSocektHandler.onError(e); - }); - } + channel.pipeline().addLast(new LocoCodec(locoSocketHandler, waitList)); + Thread.ofVirtual().start(locoSocketHandler::onConnect); + + final CompletableFuture closeFuture = new CompletableFuture<>(); // 네티 퓨처 sync함수가 virtual thread에서 제대로 작동하지 않습니다.(쓰레드 양보를 안함) 그래서 이렇게 해야됨 + channel.closeFuture().addListener(future -> { + closeFuture.complete(null); + }); + Thread.ofVirtual().start(() -> { + try { + closeFuture.get(); + eventLoopGroup.shutdownGracefully(); + locoSocketHandler.onDisconnect(); + alive = false; + } catch (Exception e) { + locoSocketHandler.onError(e); } - }.start(); + }); + } catch (InterruptedException e) { - handlerPool.execute(() -> { - locoSocektHandler.onError(e); + Thread.ofVirtual().start(() -> { + locoSocketHandler.onError(e); }); } } @@ -116,21 +114,16 @@ public class LocoSocket { waitList.remove(packetId); return result; } catch (Exception e) { - handlerPool.execute(() -> { - locoSocektHandler.onError(e); - }); + locoSocketHandler.onError(e); } return null; } public void close() { if (!alive) return; - handlerPool.execute(() -> { - locoSocektHandler.onDisconnect(); - }); eventLoopGroup.shutdownGracefully(); channel.close(); - handlerPool.execute(locoSocektHandler::onDisconnect); + Thread.ofVirtual().start(locoSocketHandler::onDisconnect); alive = false; } diff --git a/src/main/java/com/github/netricecake/loco/codec/LocoCodec.java b/src/main/java/com/github/netricecake/loco/codec/LocoCodec.java index 887b867..253569f 100644 --- a/src/main/java/com/github/netricecake/loco/codec/LocoCodec.java +++ b/src/main/java/com/github/netricecake/loco/codec/LocoCodec.java @@ -10,7 +10,6 @@ import io.netty.handler.codec.MessageToMessageCodec; import java.util.List; import java.util.Map; import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutorService; import java.util.concurrent.Future; public class LocoCodec extends MessageToMessageCodec { @@ -20,13 +19,10 @@ public class LocoCodec extends MessageToMessageCodec { private final Map> waitList; - private final LocoSocketHandler locoSocektHandler; + private final LocoSocketHandler locoSocketHandler; - private final ExecutorService handlerPool; - - public LocoCodec(LocoSocketHandler locoSocektHandler, ExecutorService handlerPool, Map> waitList) { - this.locoSocektHandler = locoSocektHandler; - this.handlerPool = handlerPool; + public LocoCodec(LocoSocketHandler locoSocketHandler, Map> waitList) { + this.locoSocketHandler = locoSocketHandler; this.waitList = waitList; } @@ -68,16 +64,16 @@ public class LocoCodec extends MessageToMessageCodec { } if (currentLocoPacket.getBodyLength() > buffer.length) break; byte[] body = ByteUtil.sliceBytes(buffer, 0, currentLocoPacket.getBodyLength()); - //System.out.println(currentLocoPacket.getMethod()); - //System.out.println(BsonUtil.bsonToJson(body)); + System.out.println(currentLocoPacket.getMethod()); + System.out.println(BsonUtil.bsonToJson(body)); buffer = ByteUtil.sliceBytes(buffer, currentLocoPacket.getBodyLength(), buffer.length - currentLocoPacket.getBodyLength()); currentLocoPacket.setBody(body); if (waitList.containsKey(currentLocoPacket.getPacketId())) { ((CompletableFuture) waitList.get(currentLocoPacket.getPacketId())).complete(currentLocoPacket); } else { final LocoPacket p = currentLocoPacket; - handlerPool.execute(() -> { - locoSocektHandler.onPacket(p); + Thread.ofVirtual().start(() -> { + locoSocketHandler.onPacket(p); }); } currentLocoPacket = null;