คู่มือ Java ฉบับทันสมัย (อัปเดตล่าสุดปี 2025)

 คู่มือ Java ฉบับทันสมัย (อัปเดตล่าสุดปี 2025) บทนำ Java ยังคงเป็นภาษายอดนิยมที่ได้รับความนิยมอย่างต่อเนื่องตั้งแต่ยุค 1990 จนถึงปัจจุบัน ในปี 2025 Java ได้ก้าวหน้าอย่างมากทั้งด้านภาษาหลักและเครื่องมือสนับสนุน ล่าสุด Java 24 ได้เปิดตัวออกมาแล้ว และ Java 21 เป็นเวอร์ชัน LTS (Long-Term Support) ที่แนะนำให้ใช้งานสำหรับระบบจริงในระยะยาว บทความนี้จะช่วยให้คุณเข้าใจภาพรวมของ Java เวอร์ชันล่าสุด รวมถึงฟีเจอร์เด่น โครงสร้างภาษาที่ควรรู้ และแนวทางการพัฒนา Java ยุคใหม่ ภาพรวมเวอร์ชัน Java ล่าสุด เวอร์ชัน สถานะ วันเปิดตัว Java 24 เวอร์ชันล่าสุด มีนาคม 2025 Java 21 เวอร์ชัน LTS ล่าสุด กันยายน 2023 Java 17 LTS รุ่นก่อนหน้า กันยายน 2021 Java 11 LTS เก่า กันยายน 2018 โครงสร้างพื้นฐานของภาษา Java คลาสและอ็อบเจกต์ : โครงสร้างหลักของโปรแกรม Java Primitive Types : int, double, char, boolean เป็นต้น Control Statements : if, switch, while, for, do-while Methods : การแยกโค้ดเป็นหน่วยที่นำกลับมาใช้ซ้ำได้ Array และ Collection : จัดเก็บและจัดการข้อมูลหลายรายการ Exception Handling : try-catch-finally OOP Co...

การใช้งาน RPC (Remote Procedure Call) ด้วย Java พร้อมตัวอย่างเกมออนไลน์ (ต่อ)

เพื่อให้สามารถอัปเดตสถานะของผู้เล่นคนอื่นในเกมออนไลน์ผ่าน RPC ได้ คุณสามารถใช้ฟีเจอร์ Server Streaming RPC ของ gRPC เพื่อให้เซิร์ฟเวอร์ส่งข้อมูลสถานะของผู้เล่นแบบเรียลไทม์ไปยังไคลเอนต์ที่กำลังเชื่อมต่ออยู่ ตัวอย่างด้านล่างแสดงวิธีการเพิ่มฟีเจอร์นี้ในเกม:


อัปเดตไฟล์ game.proto

เพิ่มเมธอดสำหรับการสตรีมสถานะของผู้เล่น:

syntax = "proto3";

service GameService {
    rpc JoinGame (JoinRequest) returns (JoinResponse);
    rpc SendMove (MoveRequest) returns (MoveResponse);
    rpc StreamPlayerUpdates (PlayerUpdateRequest) returns (stream PlayerUpdateResponse);
}

message JoinRequest {
    string playerName = 1;
}

message JoinResponse {
    string welcomeMessage = 1;
}

message MoveRequest {
    string playerName = 1;
    string move = 2;
}

message MoveResponse {
    string result = 1;
}

message PlayerUpdateRequest {
    string playerName = 1; // ชื่อผู้เล่นที่ต้องการรับการอัปเดต
}

message PlayerUpdateResponse {
    string playerName = 1;
    string status = 2; // เช่น "moved UP", "joined the game", "left the game"
}

การอัปเดตเซิร์ฟเวอร์ (GameServer)

เพิ่มการจัดการสำหรับการส่งสถานะของผู้เล่นไปยังไคลเอนต์:

import io.grpc.Server;
import io.grpc.ServerBuilder;
import io.grpc.stub.StreamObserver;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class GameServer {
    private static final Map<String, String> playerStates = new HashMap<>();

    public static void main(String[] args) throws Exception {
        Server server = ServerBuilder.forPort(8080)
            .addService(new GameServiceImpl())
            .build();

        System.out.println("Server is starting...");
        server.start();
        server.awaitTermination();
    }

    static class GameServiceImpl extends GameServiceGrpc.GameServiceImplBase {
        private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);

        @Override
        public void joinGame(JoinRequest request, StreamObserver<JoinResponse> responseObserver) {
            String playerName = request.getPlayerName();
            playerStates.put(playerName, "joined the game");

            String welcomeMessage = "Welcome, " + playerName + "!";
            JoinResponse response = JoinResponse.newBuilder()
                .setWelcomeMessage(welcomeMessage)
                .build();

            responseObserver.onNext(response);
            responseObserver.onCompleted();

            System.out.println(playerName + " joined the game.");
        }

        @Override
        public void sendMove(MoveRequest request, StreamObserver<MoveResponse> responseObserver) {
            String playerName = request.getPlayerName();
            String move = request.getMove();
            playerStates.put(playerName, "moved " + move);

            MoveResponse response = MoveResponse.newBuilder()
                .setResult("Player " + playerName + " moved " + move)
                .build();

            responseObserver.onNext(response);
            responseObserver.onCompleted();

            System.out.println(playerName + " moved " + move);
        }

        @Override
        public void streamPlayerUpdates(PlayerUpdateRequest request, StreamObserver<PlayerUpdateResponse> responseObserver) {
            String subscribingPlayer = request.getPlayerName();

            scheduler.scheduleAtFixedRate(() -> {
                for (Map.Entry<String, String> entry : playerStates.entrySet()) {
                    if (!entry.getKey().equals(subscribingPlayer)) {
                        PlayerUpdateResponse update = PlayerUpdateResponse.newBuilder()
                            .setPlayerName(entry.getKey())
                            .setStatus(entry.getValue())
                            .build();

                        responseObserver.onNext(update);
                    }
                }
            }, 0, 1, TimeUnit.SECONDS);
        }
    }
}

การอัปเดตไคลเอนต์ (GameClient)

เพิ่มฟังก์ชันสำหรับการรับข้อมูลสถานะผู้เล่นแบบเรียลไทม์:

import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;
import io.grpc.stub.StreamObserver;

public class GameClient {
    public static void main(String[] args) {
        ManagedChannel channel = ManagedChannelBuilder.forAddress("localhost", 8080)
            .usePlaintext()
            .build();

        GameServiceGrpc.GameServiceBlockingStub blockingStub = GameServiceGrpc.newBlockingStub(channel);
        GameServiceGrpc.GameServiceStub asyncStub = GameServiceGrpc.newStub(channel);

        // Join the game
        JoinRequest joinRequest = JoinRequest.newBuilder()
            .setPlayerName("Alice")
            .build();

        JoinResponse joinResponse = blockingStub.joinGame(joinRequest);
        System.out.println(joinResponse.getWelcomeMessage());

        // Start listening to player updates
        PlayerUpdateRequest updateRequest = PlayerUpdateRequest.newBuilder()
            .setPlayerName("Alice")
            .build();

        asyncStub.streamPlayerUpdates(updateRequest, new StreamObserver<PlayerUpdateResponse>() {
            @Override
            public void onNext(PlayerUpdateResponse response) {
                System.out.println("Update: " + response.getPlayerName() + " " + response.getStatus());
            }

            @Override
            public void onError(Throwable t) {
                System.err.println("Error receiving updates: " + t.getMessage());
            }

            @Override
            public void onCompleted() {
                System.out.println("Player updates completed.");
            }
        });

        // Simulate player move
        MoveRequest moveRequest = MoveRequest.newBuilder()
            .setPlayerName("Alice")
            .setMove("UP")
            .build();

        MoveResponse moveResponse = blockingStub.sendMove(moveRequest);
        System.out.println(moveResponse.getResult());

        // Keep client alive to receive updates
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        channel.shutdown();
    }
}

การทดสอบ

  1. รันเซิร์ฟเวอร์ (GameServer)

    • เซิร์ฟเวอร์จะเริ่มทำงานและพร้อมให้ไคลเอนต์เชื่อมต่อ.
  2. รันไคลเอนต์ (GameClient)

    • ผู้เล่น Alice จะเข้าร่วมเกมและสามารถส่งคำสั่งการเคลื่อนไหว.
    • ไคลเอนต์จะรับข้อมูลสถานะของผู้เล่นคนอื่น เช่น การเคลื่อนไหวหรือการเข้าร่วมเกม.

ผลลัพธ์ที่คาดหวัง

ตัวอย่างข้อความบนไคลเอนต์:

Welcome, Alice!
Update: Bob joined the game
Update: Bob moved DOWN
Player Alice moved UP

ข้อสังเกต

  • คุณสามารถเพิ่มการจัดการสถานะผู้เล่นในฐานข้อมูล เพื่อให้เซิร์ฟเวอร์สามารถจัดการสถานะได้แม้รีสตาร์ต.
  • ใช้กลไก onError หรือ onCompleted เพื่อจัดการการเชื่อมต่อที่หลุด.

การออกแบบนี้สามารถขยายได้ง่ายสำหรับเกมที่ซับซ้อนขึ้น! 🎮

ความคิดเห็น

โพสต์ยอดนิยมจากบล็อกนี้

สอนสร้างเกมส์บริหารเหตุการณ์ต่างๆในร้านนวด

คู่มือ Java ฉบับทันสมัย (อัปเดตล่าสุดปี 2025)