Spring Boot 3.2 ve üzeri sürümler, JDK 21’in sanal thread desteğini otomatik olarak yapılandırarak @Async
anotasyonuyla basit ve yüksek performanslı asenkron işlemler yapmanıza imkan tanır.
🌟 Neden Spring Boot'ta Sanal Thread Kullanmalıyız?
- Hafif Maliyet: Sanal thread’ler, geleneksel platform thread’lere kıyasla çok daha az kaynak kullanır.
- Bloklamasız:
@Async
ile işaretlenen metodlar ana thread’i meşgul etmeden çalışır. - Yüksek Ölçeklenebilirlik: Binlerce concurrent iş yükünü düşük bellek ayak iziyle yönetir.
- Basit Konfigürasyon: Tek bir özellik (property) ekleyerek tüm executor ve scheduler’ları sanal thread’li yapar.
🌟 Ön Koşullar
- ☕ Java Development Kit (JDK) 21 veya üzeri
- 📦 Spring Boot 3.2+
- 🔤 IDE (IntelliJ IDEA, Eclipse vb.)
🛠️ 1. Bağımlılıkları Ekle
Asenkron işleme olanak tanıyan spring-boot-starter-web
paketini projenize ekleyin.
Maven:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
Gradle:
implementation 'org.springframework.boot:spring-boot-starter-web'
🛠️ 2. Sanal Thread’leri Aktifleştir
application.yml
veya application.properties
dosyanıza şu satırı ekleyin:
spring: threads: virtual: enabled: true
spring.threads.virtual.enabled=true
Bu ayar, aşağıdakileri otomatik yapılandırır:
applicationTaskExecutor
(Async)- Task scheduler (
@Scheduled
) - HTTP sunucu thread havuzları (Tomcat/Jetty)
📋 3. Asenkron Desteği Aktif Etme
Ana uygulama sınıfınıza @EnableAsync
ekleyin:
package com.example.async; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.scheduling.annotation.EnableAsync; @SpringBootApplication @EnableAsync public class AsyncVirtualApplication { public static void main(String[] args) { SpringApplication.run(AsyncVirtualApplication.class, args); } }
package com.example.async import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication import org.springframework.scheduling.annotation.EnableAsync @SpringBootApplication @EnableAsync class AsyncVirtualApplication fun main(args: Array<String>) { runApplication<AsyncVirtualApplication>(*args) }
📖 4. Asenkron Servis Tanımla
@Async
anotasyonlu metodlar sanal thread üzerinde çalışır:
package com.example.async; import lombok.extern.slf4j.Slf4j; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; import java.time.LocalTime; import java.util.concurrent.CompletableFuture; @Slf4j @Service public class AsyncVirtualService { @Async public void runTask() { log.info("[{}] Asenkron başlatıldı: {}", LocalTime.now(), Thread.currentThread()); try { Thread.sleep(1000); } catch (InterruptedException ignored) {} log.info("[{}] Asenkron tamamlandı: {}", LocalTime.now(), Thread.currentThread()); } @Async public CompletableFuture<String> runAndReturn() throws InterruptedException { Thread.sleep(500); return CompletableFuture.completedFuture("Tamamlandı"); } }
package com.example.async import org.slf4j.LoggerFactory import org.springframework.scheduling.annotation.Async import org.springframework.stereotype.Service import java.time.LocalTime import java.util.concurrent.CompletableFuture @Service class AsyncVirtualService { private val log = LoggerFactory.getLogger(AsyncVirtualService::class.java) @Async fun runTask() { log.info("[{}] Asenkron başlatıldı: {}", LocalTime.now(), Thread.currentThread()) try { Thread.sleep(1000) } catch (_: InterruptedException) {} log.info("[{}] Asenkron tamamlandı: {}", LocalTime.now(), Thread.currentThread()) } @Async fun runAndReturn(): CompletableFuture<String> { Thread.sleep(500) return CompletableFuture.completedFuture("Tamamlandı") } }
🔄 5. REST Controller ile Tetikle
Aşağıdaki endpoint’leri kullanarak servis metodlarını tetikleyin:
package com.example.async; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("/async") @RequiredArgsConstructor public class AsyncVirtualController { private final AsyncVirtualService service; @GetMapping("/run") public String triggerRun() { service.runTask(); return "Asenkron sanal thread görevi tetiklendi"; } @GetMapping("/run-return") public String triggerRunAndReturn() throws Exception { var future = service.runAndReturn(); return future.get(); } }
package com.example.async import org.springframework.web.bind.annotation.GetMapping import org.springframework.web.bind.annotation.RequestMapping import org.springframework.web.bind.annotation.RestController import lombok.RequiredArgsConstructor @RestController @RequestMapping("/async") @RequiredArgsConstructor class AsyncVirtualController(private val service: AsyncVirtualService) { @GetMapping("/run") fun triggerRun(): String { service.runTask() return "Asenkron sanal thread görevi tetiklendi" } @GetMapping("/run-return") @Throws(Exception::class) fun triggerRunAndReturn(): String { val future = service.runAndReturn() return future.get() } }
▶️ Uygulamayı Çalıştır
./mvnw spring-boot:run # veya gradle bootRun
🧪 Endpointleri Test Et
Void görevi tetikle
curl http://localhost:8080/async/run
Sanal thread başlangıç/bitiş log’larını kontrol edin.
Sonuç döndüren görevi tetikle
curl http://localhost:8080/async/run-return # dönen: "Tamamlandı"
Spring Boot’ta sanal thread’ler üzerinde çalışan @Async
desteği ile yapılandırmanız minimal, performansınız maksimum olur.