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버전 이전
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 이 자주 일어나는 서비스에 매우 좋은 효과를 기대할 수 있다.
[기존 스레드]
i/o, interrupt, sleep 시 자바 스레드 block 되어 → os 커널 스레드가 다른 자바 스레드로 교체(컨텍스트 스위칭 발생)
컨텍스트 스위칭이 문제가 되는 이유는 그만큼 교환하는 과정에서 cpu는 아무것도 하지 않는게 큰 손실이다.
[Virtual Thread]
플뢧폼 쓰레드에의해 virtual 쓰레드가 관리되는 구조이다.
경량화라고 했던 이유는 바로 메모리적 차이가 있기 때문이다.
[주의사항]
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);
}