اولین بار که با کلاس Future در Scala و بعدش Akka آشنا شدم که با اون میشد با یک سبک جدید و ساده تر برنامه نویسی concurrent کرد خیلی مشتاق بودم که معادلی براش تو دنیای جاوا پیدا کنم. متاسفانه اینترفیس Future که در جاوا 5 معرفی شده بود بسیار نقص داره و نمی توان کارهای زیبایی که با Future در اسکالا انجام میشه رو باهاش انجام داد. تا اینکه در Play Framework با Promise آشنا شدم که تقریبا معادل جاوایی Future در اسکالا ولی با امکانات محدودتر بود.

سبک برنامه نویسی concurrent با Future یک سبک functional که هم کدنویسی concurrent رو ساده تر می کنه و هم خواناتر. جاوا 8 با آوردن کلاس CompletableFuture و همراهی Lambda expression ها و Stream ها این سبک برنامه نویسی concurrent به سبک functional رو برای توسعه دهندگان جاوا به ارمغان آورده. در مثال زیر یک نام و یک عدد قرار است با تاخیر بدست بیایند ولی برای چاپ خروجی به وجود نتیجه هر دو محاسبه احتیاج است که با استفاده از CompletableFuture آن دو مقدار بر روی یک ThreadPool جدید محاسبه می شوند و با اینکه مقدار نام زودتر بدست می آید ولی باید منتظر بماند تا مقدار عدد نیز محاسبه شود:

    public static void main(String[] args) { 
 
        CompletableFuture<Integer> futureNumber = CompletableFuture.supplyAsync(() -> { 
            delay(2000); 
            System.out.println("getting number finish"); 
            return 12345; 
        }, executor); 
 
        CompletableFuture<String> futureName = CompletableFuture.supplyAsync(() -> { 
            delay(1000); 
            System.out.println("getting name finish"); 
            return "Saeed"; 
        }, executor); 
 
        System.out.println("do some normal work"); 
 
        futureNumber.thenCombineAsync(futureName, (number, name) -> { 
            System.out.println(name + " " + number); 
            return null; 
        }, executor).join(); 
 
    } 
 
    private static final Executor executor = Executors.newFixedThreadPool(10, 
            r -> { 
                Thread thread = new Thread(r); 
                thread.setDaemon(true); 
                return thread; 
            } 
    ); 
 
    public static void delay(long time) { 
        try { 
            Thread.sleep(time); 
        } catch (InterruptedException e) { 
            throw new RuntimeException(e); 
        } 
    } 

 

یکی دیگه از قابلیت های خوب CompletableFuture استفاده از آنها در Stream های جاوا 8 بخصوص وقتی از parallel stream ها استفاده می کنیم.