Callable / Future

ümit Samimi
2 min readApr 7, 2022

Yazı dizimizin 3. bölümüne geldik. Bir önceki bölümü okumak isterseniz, linki aşağıya bırakıyorum.

Önceki yazıda Thread’leri işlemiştik ve Java’da bir thread nasıl oluşturulur örneklerini yapmıştık. Bu örneklerde sınıfımızı Runnable interface’i üzerinden implemente etmiştik ve run methodunun içeriğini kendi ihtiyacımıza göre doldurmuştuk fakat run methodunun imzasında geri dönüş değeri void. Yani thread çalıştıktan sonra geriye bir şey dönmüyor.

public class Task implements Runnable {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
}

Peki ya dönmesine ihtiyacımız varsa? O zaman Callable’ı kullanmamız gerekiyor.

public class ThreadExample {
public static void main(String[] args) throws InterruptedException, ExecutionException {
System.out.println("Starting....");
final int coreSize = 2;
ExecutorService executorService = Executors.newFixedThreadPool(coreSize);
Future<String> future = executorService.submit(new Task());
System.out.println(future.get());
System.out.println("Hello world");
}

static class Task implements Callable<String> {
@Override
public String call() throws InterruptedException {
Thread.sleep(10000);
return Thread.currentThread().getName();
}
}
}

Callable<String> arayüzü üzerinden Task sınıfımızı implemente ettik. Burada belirttiğimiz sınıf seviyesindeki generic “String” sayesinde call() methodunun geri dönüş değeri String türünden oldu.

Burada önemli bir nokta var. future.get() dediğimiz zaman, methodun döndüğü sonucu alıyor. Böylelikle geri dönüş değerini elde ettik fakat method uzun sürüyorsa? Bizim örneğimizde method yaklaşık olarak 10 sn sürüyor. future.get() dedikten sonra ben ekrana da hello world print etmek istiyorum fakat future’ın tamamlanmasını beklemek zorundayım. Yani “hello world” yazması için 10 sn boyunca future.get()’i bekleyeceğim.

Öyle ise aslında burada bir bloklanma var değil mi? Bitmesini, sonuçlanmasını beklememek için bir timeout süresi belirleyebiliriz aslında

future.get(1, TimeUnit.SECONDS)

Özet olarak şunu söyleyebiliriz. Eğer oluşturduğumuz thread’in geri dönüş değeri olmasını istiyorsak, Callable kullanmalıyız. Callable’ın geri dönüş değerini alacağımız zaman da dikkatli olmalıyız çünkü geri dönüş değerini beklerken block durumuna düşeceksek, thread kullanmanın pek de bir anlamı olmayabilir.

Peki alternatiflerimiz nelerdir? Tabi ki CompletableFuture.

Main thread’den ayrı bir thread’de işlem yaptığımızda, ayrık işlem bittiğinde şunu yap(thenApply()) gibi bir özelliğe sahip CompletableFuture.

public class Test {

public static void main(String[] args) {
CompletableFuture<Void> completableFuture = CompletableFuture.supplyAsync(
() -> {
sleep(3000);
return 2022;
}
).thenApply(year -> "hello "+ year)
.thenAccept(s-> System.out.println(s));

completableFuture.join();


}

private static void sleep(long millis){
try {
Thread.sleep(millis);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

--

--