HomeAboutMeBlogGuest
© 2025 Sejin Cha. All rights reserved.
Built with Next.js, deployed on Vercel
✍🏻
Learnary (learn - diary)
/
JAVA 21

JAVA 21

progress
Done
Tags
Java
2023년 하반기에 17에 이은 LTS 버전 중 새 버전이 출시되었다.개선된 RECORD 개선된 SIWTCHSequenced CollectionsUnnamed Patterns and Variables (Preview)Unnamed Classes and Instance Main Methods (Preview)Virtual Threads

2023년 하반기에 17에 이은 LTS 버전 중 새 버전이 출시되었다.

개선된 RECORD

Object o = new GrapeRecord(Color.BLUE, 2); // java 21 이전 if (o instanceof GrapeRecord grape) { System.out.println("This grape has " + grape.nbrOfPits() + " pits."); } // 21 이후 : 타입 클래스 선언이후 매개변수 포함하여 선언 가능해지며 접근성도 좋아짐 if (o instanceof GrapeRecord(Color color, Integer nbrOfPits)) { System.out.println("This grape has " + nbrOfPits + " pits."); // 중첩 레코드 또한 지원 if (o instanceof SpecialGrapeRecord(GrapeRecord grape, boolean special)) { System.out.println("This grape has " + grape.nbrOfPits() + " pits."); } if (o instanceof SpecialGrapeRecord(GrapeRecord(Color color, Integer nbrOfPits), boolean special)) { System.out.println("This grape has " + nbrOfPits + " pits."); } }

개선된 SIWTCH

비교 성공시 바로 사용 가능
// 비교 성공시 바로 사용 가능 static String formatterPatternSwitch(Object obj) { return switch (obj) { case Integer i -> String.format("int %d", i); case Long l -> String.format("long %d", l); case Double d -> String.format("double %f", d); default -> obj.toString(); }; }
null인 경우도 case로 처리 가능
static void testFooBarNew(String s) { switch (s) { case null -> System.out.println("Oops"); case "Foo", "Bar" -> System.out.println("Great"); default -> System.out.println("Ok"); } }
enum 타입일 경우
static void exhaustiveSwitchWithBetterEnumSupport(CardClassification c) { switch (c) { case Suit.CLUBS -> { System.out.println("It's clubs"); } case Suit.DIAMONDS -> { System.out.println("It's diamonds"); } case Suit.HEARTS -> { System.out.println("It's hearts"); } case Suit.SPADES -> { System.out.println("It's spades"); } } }
복수 조건 사용 가능
static void testStringEnhanced(String response) { switch (response) { case null -> { } case "y", "Y" -> { System.out.println("You got it"); } case "n", "N" -> { System.out.println("Shame"); } case String s when s.equalsIgnoreCase("YES") -> { System.out.println("You got it"); } case String s when s.equalsIgnoreCase("NO") -> { System.out.println("Shame"); } } }

Sequenced Collections

첫번째 요소와 마지막 요소에 엑세스하고 해당 역순으로 처리하기 위한 통일된 API 제공
 
 
21버전 이전
notion image
21버전 이후
interface SequencedCollection<E> extends Collection<E> { // new method SequencedCollection<E> reversed(); // methods promoted from Deque void addFirst(E); void addLast(E); E getFirst(); E getLast(); E removeFirst(); E removeLast(); }

Unnamed Patterns and Variables (Preview)

  • 구성 요소의 이름이나 유형을 명시하지 않고 이름 없는 패턴 및 변수, 밑줄 문자로 표시
21버전 이전
int total = 0; for (Order order : orders) { // 사실상 사용되지 않는 order if (total < LIMIT) { ... total++ ... } }
21버전 이후
int total = 0; for (Order _ : orders) { if (total < LIMIT) { ... total++ ... } }

Unnamed Classes and Instance Main Methods (Preview)

21버전 이전
public static void main(String[] args) → main 시작
21버전 이후
void main() → main 시작
 

Virtual Threads

  • 일반적인 쓰레드보다 경량화된 쓰레드 이다.
 
해당 쓰레드는 컨텍스트 스위칭이 기존 쓰레드보다 가볍다.
그렇기 때문에 io 작업과 같은 blocking 이 자주 일어나는 서비스에 매우 좋은 효과를 기대할 수 있다.
 
[기존 스레드]
 
notion image
  • i/o, interrupt, sleep 시 자바 스레드 block 되어 → os 커널 스레드가 다른 자바 스레드로 교체(컨텍스트 스위칭 발생)
 
컨텍스트 스위칭이 문제가 되는 이유는 그만큼 교환하는 과정에서 cpu는 아무것도 하지 않는게 큰 손실이다.
 
[Virtual Thread]
 
notion image
 
  • 플뢧폼 쓰레드에의해 virtual 쓰레드가 관리되는 구조이다.
  • 경량화라고 했던 이유는 바로 메모리적 차이가 있기 때문이다.
    • notion image
       
      [주의사항]
    • virtual 는 메모리 관점에서 매우 가볍기 때문에 쓰레드 풀을 만드는 행위 자체가 낭비가 될 수 있다함
    • Thread Local에 무거운 객체를 저장하지 않아야 한다. 그러면 context switching이 가볍다 라는 이점이 사라짐
    • cpu bound 작업에는 비효율적 이다
    • Pinned Issue
      • synchronized, parallelStream 사용 시, virtual Thread가 carrier thread에 고정되는 상태로 작동해 성능이 저하됨
      • lock 이 필요한 경우에 ReentrantLock으로 대체 고려 필요
       
      virtual 코드 구현체 ⇒ 기존 쓰레드 상속,
      // Thread.java public static void sleep(long millis) throws InterruptedException { if (millis < 0) { throw new IllegalArgumentException("timeout value is negative"); } long nanos = MILLISECONDS.toNanos(millis); ThreadSleepEvent event = beforeSleep(nanos); try { if (currentThread() instanceof VirtualThread vthread) { vthread.sleepNanos(nanos); } else { sleep0(nanos); } } finally { afterSleep(event); } } ==== // org.springframework.boot.autoconfigure.web.embedded.EmbeddedWebServerFactoryCustomizerAutoConfiguration.java @Configuration( proxyBeanMethods = false ) @ConditionalOnClass({Tomcat.class, UpgradeProtocol.class}) public static class TomcatWebServerFactoryCustomizerConfiguration { public TomcatWebServerFactoryCustomizerConfiguration() { } @Bean public TomcatWebServerFactoryCustomizer tomcatWebServerFactoryCustomizer(Environment environment, ServerProperties serverProperties) { return new TomcatWebServerFactoryCustomizer(environment, serverProperties); } @Bean @ConditionalOnThreading(Threading.VIRTUAL) TomcatVirtualThreadsWebServerFactoryCustomizer tomcatVirtualThreadsProtocolHandlerCustomizer() { return new TomcatVirtualThreadsWebServerFactoryCustomizer(); } } // org.springframework.boot.autoconfigure.web.embedded.TomcatVirtualThreadsWebServerFactoryCustomizer.java // ============================================================================ // ** virtual thread 활성화하면 executor 별도로 생성해줌!!!!!!!!!!!1 // ============================================================================ public void customize(ConfigurableTomcatWebServerFactory factory) { factory.addProtocolHandlerCustomizers(new TomcatProtocolHandlerCustomizer[]{(protocolHandler) -> { protocolHandler.setExecutor(new VirtualThreadExecutor("tomcat-handler-")); }}); } // org.apache.tomcat.util.threads.VirtualThreadExecutor.java public VirtualThreadExecutor(String namePrefix) { this.threadBuilder = this.jreCompat.createVirtualThreadBuilder(namePrefix); }
       
      주의사항
       
      Virtual Thread의 기본 개념 이해하기
      JDK에 정식 도입된 Virtual Thread는 기존의 KLT(kernel-level thread)와 ULT(user-level thread)를 1:1 매핑하여..
      Virtual Thread의 기본 개념 이해하기
      https://d2.naver.com/helloworld/1203723
      Virtual Thread의 기본 개념 이해하기