CompletableFuture এবং Asynchronous Programming

Java Technologies - জাভা কনকারেন্সি (Java Concurrency)
139
139

CompletableFuture হল জাভা কনকারেন্সি API-র একটি শক্তিশালী টুল যা অ্যাসিঙ্ক্রোনাস প্রোগ্রামিং সহজ এবং কার্যকর করে। এটি জাভা 8 এ চালু হয় এবং এটি non-blocking, event-driven, এবং callback-based অ্যাসিঙ্ক্রোনাস প্রোগ্রামিং সমর্থন করে।


CompletableFuture এর বৈশিষ্ট্য

  1. Non-blocking API: অন্য থ্রেড ব্লক না করেই কাজ সম্পন্ন করা যায়।
  2. Chaining: একাধিক অ্যাসিঙ্ক্রোনাস অপারেশন চেইন করা যায়।
  3. Combine Operations: একাধিক ফিউচার একত্রে চালানো যায়।
  4. Exception Handling: অ্যাসিঙ্ক্রোনাস কাজের ব্যতিক্রম সহজে পরিচালনা করা যায়।

CompletableFuture এর প্রধান মেথড

মেথডবর্ণনা
supplyAsyncএকটি ভ্যালু প্রদানকারী অ্যাসিঙ্ক্রোনাস কাজ শুরু করে।
runAsyncকোনো ভ্যালু ছাড়া অ্যাসিঙ্ক্রোনাস কাজ শুরু করে।
thenApplyআগের কাজের রেজাল্ট প্রসেস করে একটি নতুন ফলাফল তৈরি করে।
thenAcceptআগের কাজের রেজাল্ট গ্রহণ করে, তবে কোনো নতুন ফলাফল দেয় না।
thenRunআগের কাজের পর কিছু কাজ চালায়, তবে কোনো ভ্যালু রিটার্ন করে না।
thenCombineদুটি ফিউচার একত্রে প্রসেস করে।
exceptionallyব্যতিক্রম পরিচালনা করে এবং একটি ডিফল্ট মান প্রদান করে।
whenCompleteকাজ সম্পন্ন হওয়ার পর রেজাল্ট বা ব্যতিক্রম পরিচালনা করে।
joinরেজাল্ট পাওয়ার জন্য ব্লক করে।

CompletableFuture এর উদাহরণ

১. সহজ অ্যাসিঙ্ক্রোনাস কাজ

import java.util.concurrent.CompletableFuture;

public class SimpleCompletableFuture {
    public static void main(String[] args) {
        CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
            System.out.println("Running an asynchronous task!");
        });

        // কাজ সম্পন্ন না হওয়া পর্যন্ত অপেক্ষা করুন
        future.join();
        System.out.println("Task completed!");
    }
}

২. supplyAsync এবং thenApply ব্যবহার করে চেইনিং

import java.util.concurrent.CompletableFuture;

public class CompletableFutureChaining {
    public static void main(String[] args) {
        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            return "Hello";
        }).thenApply(result -> {
            return result + ", World!";
        }).thenApply(result -> {
            return result + " How are you?";
        });

        System.out.println(future.join());
    }
}

৩. একাধিক ফিউচার কম্বাইন করা

import java.util.concurrent.CompletableFuture;

public class CompletableFutureCombine {
    public static void main(String[] args) {
        CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {
            return "Hello";
        });

        CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
            return "World";
        });

        CompletableFuture<String> combinedFuture = future1.thenCombine(future2, (result1, result2) -> {
            return result1 + " " + result2;
        });

        System.out.println(combinedFuture.join());
    }
}

৪. ব্যতিক্রম পরিচালনা

import java.util.concurrent.CompletableFuture;

public class CompletableFutureExceptionHandling {
    public static void main(String[] args) {
        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            throw new RuntimeException("Something went wrong!");
        }).exceptionally(ex -> {
            System.out.println("Exception occurred: " + ex.getMessage());
            return 0; // ডিফল্ট মান
        });

        System.out.println("Result: " + future.join());
    }
}

৫. অ্যাসিঙ্ক্রোনাস কাজের উপর কাজ সম্পন্নের পরে কিছু করা

import java.util.concurrent.CompletableFuture;

public class CompletableFutureWhenComplete {
    public static void main(String[] args) {
        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            return "Task result";
        }).whenComplete((result, ex) -> {
            if (ex == null) {
                System.out.println("Task completed successfully: " + result);
            } else {
                System.out.println("Task failed: " + ex.getMessage());
            }
        });

        future.join();
    }
}

অ্যাসিঙ্ক্রোনাস প্রোগ্রামিং: বাস্তব জগতে উদাহরণ

REST API থেকে ডেটা ফেচ করা

import java.util.concurrent.CompletableFuture;

public class AsyncApiCallExample {
    public static void main(String[] args) {
        CompletableFuture<Void> future = CompletableFuture.supplyAsync(() -> {
            return fetchDataFromApi(); // একটি ফেক API কল
        }).thenAccept(data -> {
            System.out.println("Data fetched: " + data);
        });

        future.join(); // অ্যাসিঙ্ক্রোনাস কাজ শেষ না হওয়া পর্যন্ত অপেক্ষা
    }

    private static String fetchDataFromApi() {
        try {
            Thread.sleep(2000); // API কলের জন্য অপেক্ষা
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "Sample API Data";
    }
}

  1. CompletableFuture অ্যাসিঙ্ক্রোনাস কাজ সহজ এবং কার্যকর করে।
  2. Chaining এবং Combining অপারেশন একাধিক কাজ পরিচালনা সহজ করে।
  3. Exception Handling এর মাধ্যমে অ্যাসিঙ্ক্রোনাস কাজের ব্যতিক্রম হ্যান্ডেল করা যায়।
  4. Non-blocking Nature বড় স্কেল অ্যাপ্লিকেশনে পারফরম্যান্স উন্নত করে।

ব্যবহারিক ক্ষেত্রে: ডেটা প্রসেসিং, REST API কল, ডেটাবেস অপারেশন, ফাইল হ্যান্ডলিং ইত্যাদির জন্য এটি ব্যাপকভাবে ব্যবহৃত হয়।

Content added By

CompletableFuture কি এবং কেন দরকার?

136
136

CompletableFuture হলো জাভা কনকারেন্সি API-তে থাকা একটি শক্তিশালী ক্লাস, যা অ্যাসিনক্রোনাস (asynchronous) প্রোগ্রামিংয়ের জন্য ব্যবহৃত হয়। এটি জাভা 8-এ পরিচিত হয় এবং অনেক সুবিধাজনক মেথড সরবরাহ করে যা অ্যাসিনক্রোনাস কাজ সম্পাদনে সাহায্য করে।


CompletableFuture এর উদ্দেশ্য

  1. অ্যাসিনক্রোনাস প্রোগ্রামিং সহজ করা:
    • CompletableFuture এর মাধ্যমে আপনি থ্রেড ম্যানেজমেন্ট বা লকিং ছাড়াই অ্যাসিনক্রোনাস কাজ করতে পারেন।
  2. নন-ব্লকিং কোড:
    • এটি একটি নন-ব্লকিং মেকানিজম, যেখানে থ্রেডগুলি কাজ শেষ হওয়ার জন্য অপেক্ষা না করে অন্য কাজ করতে পারে।
  3. চেইনড প্রসেসিং:
    • একাধিক অ্যাসিনক্রোনাস কাজ চেইনের মতো সম্পাদন করতে সাহায্য করে।
  4. থ্রেড পুল ব্যবস্থাপনা:
    • ডিফল্ট থ্রেড পুল ব্যবহার করে কাজ পরিচালনা করে, তবে প্রয়োজনে কাস্টম থ্রেড পুলও ব্যবহার করা যায়।

CompletableFuture এর সুবিধা

  • অ্যাসিনক্রোনাস এবং ইভেন্ট-ড্রিভেন প্রোগ্রামিং সহজ করে।
  • ব্লকিং কোড থেকে মুক্তি দেয়।
  • একাধিক কাজ সমান্তরালভাবে সম্পাদন করতে পারে।
  • একাধিক CompletableFuture কে একত্রে ব্যবহার করে জটিল কনকারেন্সি সমস্যা সমাধান করতে পারে।

CompletableFuture ব্যবহার উদাহরণ

১. বেসিক CompletableFuture ব্যবহার

import java.util.concurrent.CompletableFuture;

public class BasicCompletableFutureExample {
    public static void main(String[] args) {
        // অ্যাসিনক্রোনাস টাস্ক
        CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
            try {
                Thread.sleep(1000);
                System.out.println("Task completed!");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        System.out.println("Doing other work while task runs...");
        
        // মূল থ্রেডে কাজ শেষ হওয়ার জন্য অপেক্ষা
        future.join();
        System.out.println("Main thread done!");
    }
}

২. রিটার্ন ভ্যালু সহ CompletableFuture

import java.util.concurrent.CompletableFuture;

public class ReturnValueExample {
    public static void main(String[] args) {
        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(1000);
                return "Hello from CompletableFuture!";
            } catch (InterruptedException e) {
                e.printStackTrace();
                return null;
            }
        });

        // ফিউচারের রিটার্ন ভ্যালু প্রিন্ট
        String result = future.join();
        System.out.println(result);
    }
}

৩. CompletableFuture চেইনিং

import java.util.concurrent.CompletableFuture;

public class ChainingExample {
    public static void main(String[] args) {
        CompletableFuture<Void> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("Fetching data...");
            return "Data fetched!";
        }).thenApply(data -> {
            System.out.println("Processing data...");
            return data.toUpperCase();
        }).thenAccept(result -> {
            System.out.println("Result: " + result);
        });

        future.join();
    }
}

৪. একাধিক CompletableFuture একত্রে ব্যবহার

import java.util.concurrent.CompletableFuture;

public class CombineFuturesExample {
    public static void main(String[] args) {
        CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {
            return "Hello";
        });

        CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
            return "World";
        });

        CompletableFuture<String> combinedFuture = future1.thenCombine(future2, (result1, result2) -> {
            return result1 + " " + result2;
        });

        System.out.println(combinedFuture.join()); // Output: Hello World
    }
}

৫. Exception Handling সহ CompletableFuture

import java.util.concurrent.CompletableFuture;

public class ExceptionHandlingExample {
    public static void main(String[] args) {
        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            if (true) {
                throw new RuntimeException("Something went wrong!");
            }
            return "Success!";
        }).exceptionally(ex -> {
            System.out.println("Exception: " + ex.getMessage());
            return "Recovered from failure";
        });

        System.out.println(future.join());
    }
}

CompletableFuture কেন দরকার?

  1. সাধারণ থ্রেড API এর চেয়ে সহজ:
    • Thread, ExecutorService ব্যবহার করে ম্যানুয়াল থ্রেড ম্যানেজমেন্ট জটিল হয়, যেখানে CompletableFuture ব্যবহার সহজ।
  2. ব্লকিং এড়ানো:
    • অ্যাসিনক্রোনাস কাজ সম্পন্ন হওয়া পর্যন্ত অপেক্ষা করার প্রয়োজন নেই।
  3. বেশি পারফরম্যান্স:
    • নন-ব্লকিং অপারেশন এবং ডিফল্ট থ্রেড পুল ব্যবহার করে।
  4. ফিউচার চেইনিং:
    • একাধিক কাজ ধাপে ধাপে করতে সাহায্য করে।
  5. সিম্পল এক্সেপশন হ্যান্ডলিং:
    • এক্সেপশন ম্যানেজ করার জন্য সরাসরি মেথড (exceptionally, handle) আছে।

সেরা অনুশীলন (Best Practices)

  1. কাস্টম থ্রেড পুল ব্যবহার: ভারী লোডের জন্য কাস্টম Executor ব্যবহার করুন।
  2. অপ্রয়োজনীয় ব্লকিং এড়ান: get() এর পরিবর্তে join() ব্যবহার করুন।
  3. ঠিকমতো চেইনিং করুন: thenApply(), thenAccept() এবং thenCombine() সঠিকভাবে ব্যবহার করুন।
  4. Exception Handling নিশ্চিত করুন: অ্যাসিনক্রোনাস এক্সেপশনগুলো সঠিকভাবে পরিচালনা করুন।
  5. Debugging টুল ব্যবহার করুন: CompletableFuture এর চেইন বড় হলে ডিবাগিং কঠিন হয়, এজন্য লগিং নিশ্চিত করুন।

CompletableFuture হল জাভার একটি আধুনিক অ্যাসিনক্রোনাস প্রোগ্রামিং টুল, যা মাল্টিথ্রেডিং এবং কনকারেন্সি সমস্যাগুলো সহজ এবং কার্যকরীভাবে সমাধান করতে সহায়ক। এটি নন-ব্লকিং এবং অ্যাসিনক্রোনাস কাজ সহজে এবং পারফরম্যান্স বৃদ্ধি করে।

Content added By

CompletableFuture এর মাধ্যমে Asynchronous Task Management

129
129

CompletableFuture জাভা ৮-এ যোগ করা একটি ক্লাস, যা Future ইন্টারফেসের একটি উন্নত সংস্করণ। এটি অ্যাসিঙ্ক্রোনাস টাস্ক পরিচালনা এবং চেইনিংয়ের মাধ্যমে জটিল অপারেশন সহজ করে।


কেন CompletableFuture ব্যবহার করবেন?

  1. অ্যাসিঙ্ক্রোনাস টাস্ক ম্যানেজমেন্ট: runAsync এবং supplyAsync এর মাধ্যমে নন-ব্লকিং কাজ সম্পাদন।
  2. চেইনিং: টাস্ক চেইন করতে thenApply, thenAccept, এবং thenRun ব্যবহার।
  3. কম্পোজিশন: একাধিক টাস্কের ফলাফল একত্রিত করতে।
  4. ব্যতিক্রম হ্যান্ডলিং: exceptionally এবং handle দিয়ে সহজেই ত্রুটি পরিচালনা।
  5. ব্লকিং এড়ানো: থ্রেড ব্লক না করে কাজ পরিচালনা।

১. CompletableFuture দিয়ে একটি সাধারণ অ্যাসিঙ্ক্রোনাস টাস্ক

import java.util.concurrent.CompletableFuture;

public class CompletableFutureBasic {
    public static void main(String[] args) {
        // একটি অ্যাসিঙ্ক্রোনাস টাস্ক
        CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
            System.out.println("Task is running in: " + Thread.currentThread().getName());
        });

        // টাস্ক শেষ হলে মেসেজ প্রিন্ট
        future.thenRun(() -> System.out.println("Task completed!"));

        // মূল থ্রেড চালু রাখতে অপেক্ষা
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

২. supplyAsync দিয়ে ফলাফল প্রদান করা

import java.util.concurrent.CompletableFuture;

public class CompletableFutureSupplyAsync {
    public static void main(String[] args) {
        // অ্যাসিঙ্ক্রোনাসভাবে একটি ফলাফল প্রদান
        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("Processing in: " + Thread.currentThread().getName());
            return "Hello, CompletableFuture!";
        });

        // চেইন করে ফলাফল প্রিন্ট করা
        future.thenApply(result -> {
            return result + " Modified.";
        }).thenAccept(System.out::println);

        // মূল থ্রেড চালু রাখতে অপেক্ষা
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

৩. একাধিক CompletableFuture চেইনিং এবং কম্বিনিং

import java.util.concurrent.CompletableFuture;

public class CompletableFutureChaining {
    public static void main(String[] args) {
        // প্রথম টাস্ক
        CompletableFuture<Integer> task1 = CompletableFuture.supplyAsync(() -> {
            System.out.println("Executing Task 1");
            return 10;
        });

        // দ্বিতীয় টাস্ক
        CompletableFuture<Integer> task2 = CompletableFuture.supplyAsync(() -> {
            System.out.println("Executing Task 2");
            return 20;
        });

        // টাস্ক কম্বিন করা
        CompletableFuture<Integer> combinedTask = task1.thenCombine(task2, Integer::sum);

        // চূড়ান্ত ফলাফল প্রিন্ট
        combinedTask.thenAccept(result -> System.out.println("Final Result: " + result));

        // মূল থ্রেড চালু রাখতে অপেক্ষা
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

৪. ব্যতিক্রম হ্যান্ডলিং

import java.util.concurrent.CompletableFuture;

public class CompletableFutureExceptionHandling {
    public static void main(String[] args) {
        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("Task is running...");
            if (true) {
                throw new RuntimeException("An error occurred!");
            }
            return 10;
        });

        // ব্যতিক্রম পরিচালনা
        future.exceptionally(ex -> {
            System.out.println("Error: " + ex.getMessage());
            return 0; // ডিফল্ট মান প্রদান
        }).thenAccept(result -> System.out.println("Result: " + result));

        // মূল থ্রেড চালু রাখতে অপেক্ষা
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

৫. একটি বাস্তব উদাহরণ: ডেটাবেস এবং REST API কল সমন্বয়

import java.util.concurrent.CompletableFuture;

public class CompletableFutureRealExample {
    public static void main(String[] args) {
        // ডেটাবেস থেকে ডেটা ফেচ করা
        CompletableFuture<String> dbTask = CompletableFuture.supplyAsync(() -> {
            System.out.println("Fetching data from database...");
            return "Database Data";
        });

        // REST API থেকে ডেটা ফেচ করা
        CompletableFuture<String> apiTask = CompletableFuture.supplyAsync(() -> {
            System.out.println("Fetching data from REST API...");
            return "API Data";
        });

        // ডেটা একত্রিত করা
        CompletableFuture<String> combinedTask = dbTask.thenCombine(apiTask, (dbData, apiData) -> {
            return dbData + " + " + apiData;
        });

        // চূড়ান্ত ফলাফল প্রিন্ট
        combinedTask.thenAccept(result -> System.out.println("Combined Result: " + result));

        // মূল থ্রেড চালু রাখতে অপেক্ষা
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

৬. allOf এবং anyOf এর ব্যবহার

allOf: সমস্ত CompletableFuture শেষ হওয়া পর্যন্ত অপেক্ষা করে।

import java.util.concurrent.CompletableFuture;

public class CompletableFutureAllOf {
    public static void main(String[] args) {
        CompletableFuture<Void> allTask = CompletableFuture.allOf(
                CompletableFuture.runAsync(() -> System.out.println("Task 1")),
                CompletableFuture.runAsync(() -> System.out.println("Task 2")),
                CompletableFuture.runAsync(() -> System.out.println("Task 3"))
        );

        allTask.thenRun(() -> System.out.println("All tasks completed!"));

        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

anyOf: একটি CompletableFuture শেষ হলেই এটি চলবে।

import java.util.concurrent.CompletableFuture;

public class CompletableFutureAnyOf {
    public static void main(String[] args) {
        CompletableFuture<Object> anyTask = CompletableFuture.anyOf(
                CompletableFuture.supplyAsync(() -> {
                    System.out.println("Task 1 completed");
                    return "Result from Task 1";
                }),
                CompletableFuture.supplyAsync(() -> {
                    System.out.println("Task 2 completed");
                    return "Result from Task 2";
                })
        );

        anyTask.thenAccept(result -> System.out.println("First completed result: " + result));

        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

CompletableFuture অ্যাসিঙ্ক্রোনাস প্রোগ্রামিংয়ের জন্য একটি অত্যন্ত শক্তিশালী টুল। এটি নিম্নলিখিত সুবিধা প্রদান করে:

  • অ্যাসিঙ্ক্রোনাস টাস্ক সহজে পরিচালনা।
  • চেইনিংয়ের মাধ্যমে জটিল কাজের সরলীকরণ।
  • ত্রুটি পরিচালনা এবং টাস্ক ম্যানেজমেন্ট সহজ করা।

এই ক্লাসটি ব্যবহার করে আপনি নন-ব্লকিং এবং উচ্চ কার্যক্ষম অ্যাপ্লিকেশন তৈরি করতে পারবেন।

Content added By

thenApply(), thenAccept(), এবং thenCompose() এর ব্যবহার

114
114

জাভার CompletableFuture API হল একটি শক্তিশালী টুল, যা অ্যাসিঙ্ক্রোনাস অপারেশনগুলিকে সহজ এবং কার্যকর করে। এর মধ্যে thenApply(), thenAccept(), এবং thenCompose() হলো কয়েকটি গুরুত্বপূর্ণ মেথড। এগুলো চেইনিং এবং কম্পোজিশনের জন্য ব্যবহৃত হয়।


১. thenApply()

  • ব্যাখ্যা:
    • এটি একটি অ্যাসিঙ্ক্রোনাস কম্পিউটেশন-এর ফলাফল গ্রহণ করে এবং একটি নতুন মান রিটার্ন করে।
    • এটি Function<T, R> গ্রহণ করে, যেখানে T হল পূর্ববর্তী ধাপের ফলাফল এবং R হল নতুন ফলাফল।

ব্যবহার:

import java.util.concurrent.CompletableFuture;

public class ThenApplyExample {
    public static void main(String[] args) {
        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("Fetching data...");
            return "Hello";
        });

        CompletableFuture<String> transformedFuture = future.thenApply(data -> {
            System.out.println("Transforming data...");
            return data + ", World!";
        });

        // ফলাফল প্রিন্ট করা
        transformedFuture.thenAccept(System.out::println);
    }
}

আউটপুট:

Fetching data...
Transforming data...
Hello, World!

২. thenAccept()

  • ব্যাখ্যা:
    • এটি একটি অ্যাসিঙ্ক্রোনাস অপারেশনের ফলাফল গ্রহণ করে এবং এটি ব্যবহার করে কিছু কাজ করে।
    • এটি Consumer<T> গ্রহণ করে এবং কোনো মান রিটার্ন করে না।

ব্যবহার:

import java.util.concurrent.CompletableFuture;

public class ThenAcceptExample {
    public static void main(String[] args) {
        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("Fetching data...");
            return "Hello, World!";
        });

        // ফলাফল গ্রহণ এবং প্রিন্ট করা
        future.thenAccept(result -> {
            System.out.println("Result: " + result);
        });
    }
}

আউটপুট:

Fetching data...
Result: Hello, World!

৩. thenCompose()

  • ব্যাখ্যা:
    • এটি একটি কম্পোজিশন মেথড, যা একটি অ্যাসিঙ্ক্রোনাস অপারেশন সম্পন্ন হওয়ার পরে আরেকটি CompletableFuture অপারেশন চালায়।
    • এটি Function<T, CompletableFuture<U>> গ্রহণ করে।

ব্যবহার:

import java.util.concurrent.CompletableFuture;

public class ThenComposeExample {
    public static void main(String[] args) {
        CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {
            System.out.println("Fetching user...");
            return "User123";
        });

        CompletableFuture<String> future2 = future1.thenCompose(user -> {
            System.out.println("Fetching account for: " + user);
            return CompletableFuture.supplyAsync(() -> "Account567");
        });

        // চূড়ান্ত ফলাফল প্রিন্ট করা
        future2.thenAccept(account -> {
            System.out.println("Account fetched: " + account);
        });
    }
}

আউটপুট:

Fetching user...
Fetching account for: User123
Account fetched: Account567

সবগুলো মিলে একটি উদাহরণ

import java.util.concurrent.CompletableFuture;

public class CompletableFutureExample {
    public static void main(String[] args) {
        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("Fetching number...");
            return 10;
        });

        // `thenApply()` দিয়ে সংখ্যা দ্বিগুণ করা
        CompletableFuture<Integer> doubledFuture = future.thenApply(number -> {
            System.out.println("Doubling the number...");
            return number * 2;
        });

        // `thenAccept()` দিয়ে ফলাফল প্রিন্ট করা
        doubledFuture.thenAccept(result -> {
            System.out.println("Doubled Result: " + result);
        });

        // `thenCompose()` দিয়ে আরও একটি অ্যাসিঙ্ক্রোনাস অপারেশন
        CompletableFuture<Void> finalFuture = doubledFuture.thenCompose(result -> {
            System.out.println("Processing with result...");
            return CompletableFuture.runAsync(() -> {
                System.out.println("Final Result Processed: " + (result + 5));
            });
        });

        finalFuture.join(); // মূল থ্রেড অপেক্ষা করবে
    }
}

আউটপুট:

Fetching number...
Doubling the number...
Doubled Result: 20
Processing with result...
Final Result Processed: 25

তুলনামূলক পার্থক্য

মেথডকাজরিটার্ন টাইপ
thenApplyফলাফল রূপান্তর করে এবং নতুন মান রিটার্ন করে।CompletableFuture<U>
thenAcceptফলাফল গ্রহণ করে এবং কিছু কাজ করে, তবে কিছু রিটার্ন করে না।CompletableFuture<Void>
thenComposeএকটি অ্যাসিঙ্ক্রোনাস ফলাফল নিয়ে আরও একটি অপারেশন চালায়।CompletableFuture<U>

  • thenApply(): রূপান্তরের জন্য ব্যবহৃত হয়।
  • thenAccept(): কোনো অ্যাকশনের জন্য ব্যবহৃত হয়।
  • thenCompose(): চেইনড অ্যাসিঙ্ক্রোনাস অপারেশনগুলির জন্য ব্যবহৃত হয়।

এগুলো ব্যবহার করে জটিল অ্যাসিঙ্ক্রোনাস অপারেশনগুলি সহজে পরিচালনা করা যায়।

Content added By

Combining Multiple Futures এবং Exception Handling

136
136

Java CompletableFuture API জাভার কনকারেন্সি ফ্রেমওয়ার্কে শক্তিশালী টুল, যা অ্যাসিঙ্ক্রোনাস কম্পিউটেশন সহজ এবং কার্যকর করে।


Combining Multiple Futures

১. thenCombine() ব্যবহার করে দুটি Future যুক্ত করা

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

public class CombineFuturesExample {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        // Future 1: প্রথম সংখ্যা
        CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> {
            System.out.println("Executing Future 1...");
            return 10;
        });

        // Future 2: দ্বিতীয় সংখ্যা
        CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> {
            System.out.println("Executing Future 2...");
            return 20;
        });

        // দুটি Future এর ফলাফল যোগ করে নতুন Future তৈরি করা
        CompletableFuture<Integer> result = future1.thenCombine(future2, (num1, num2) -> num1 + num2);

        // ফলাফল প্রিন্ট করা
        System.out.println("Combined Result: " + result.get());
    }
}

ব্যাখ্যা:

  • thenCombine(): দুটি Future এর ফলাফল নিয়ে একটি নতুন ফলাফল তৈরি করে।
  • এখানে দুটি Future গাণিতিক যোগফল তৈরি করতে ব্যবহার করা হয়েছে।

২. allOf() ব্যবহার করে একাধিক Future একত্র করা

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

public class AllOfExample {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        // তিনটি Future তৈরি
        CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> "Task 1 Completed");
        CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> "Task 2 Completed");
        CompletableFuture<String> future3 = CompletableFuture.supplyAsync(() -> "Task 3 Completed");

        // সব Future একত্র করা
        CompletableFuture<Void> combinedFuture = CompletableFuture.allOf(future1, future2, future3);

        // সব Future সম্পন্ন হলে আউটপুট দেখানো
        combinedFuture.thenRun(() -> {
            try {
                System.out.println(future1.get());
                System.out.println(future2.get());
                System.out.println(future3.get());
            } catch (Exception e) {
                e.printStackTrace();
            }
        }).get();
    }
}

ব্যাখ্যা:

  • allOf(): একাধিক Future একত্র করে একটি নতুন CompletableFuture তৈরি করে।
  • এখানে তিনটি Future এর কাজ শেষ হলে আউটপুট প্রদর্শন করা হয়।

৩. anyOf() ব্যবহার করে প্রথম সম্পন্ন হওয়া Future নির্বাচন

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

public class AnyOfExample {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        // Future তৈরি
        CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "Task 1 Completed";
        });

        CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> "Task 2 Completed");

        // প্রথম সম্পন্ন হওয়া Future নির্বাচন
        CompletableFuture<Object> result = CompletableFuture.anyOf(future1, future2);

        // ফলাফল প্রিন্ট করা
        System.out.println("First Completed Task: " + result.get());
    }
}

ব্যাখ্যা:

  • anyOf(): একাধিক Future থেকে প্রথম সম্পন্ন হওয়া Future এর ফলাফল প্রদান করে।
  • এটি দ্রুত ফলাফল পেতে কার্যকর।

Exception Handling

১. exceptionally() ব্যবহার করে ব্যতিক্রম পরিচালনা

import java.util.concurrent.CompletableFuture;

public class ExceptionHandlingExample {
    public static void main(String[] args) {
        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            if (true) {
                throw new RuntimeException("Something went wrong!");
            }
            return "Success";
        }).exceptionally(ex -> {
            System.out.println("Exception: " + ex.getMessage());
            return "Fallback Result";
        });

        System.out.println("Result: " + future.join());
    }
}

ব্যাখ্যা:

  • exceptionally(): ব্যতিক্রমের সময় বিকল্প ফলাফল প্রদান করে।
  • এখানে ব্যতিক্রমের ক্ষেত্রে "Fallback Result" প্রদর্শিত হয়।

২. handle() ব্যবহার করে ব্যতিক্রম ও স্বাভাবিক ফলাফল পরিচালনা

import java.util.concurrent.CompletableFuture;

public class HandleExample {
    public static void main(String[] args) {
        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            if (true) {
                throw new RuntimeException("An error occurred!");
            }
            return "Success";
        }).handle((result, ex) -> {
            if (ex != null) {
                System.out.println("Exception: " + ex.getMessage());
                return "Handled Error Result";
            }
            return result;
        });

        System.out.println("Result: " + future.join());
    }
}

ব্যাখ্যা:

  • handle(): ব্যতিক্রম এবং স্বাভাবিক উভয় ফলাফলের জন্য কাজ করে।
  • এটি ব্যতিক্রমের ক্ষেত্রে বিকল্প ফলাফল প্রদান করে এবং স্বাভাবিক ক্ষেত্রে মূল ফলাফল প্রদান করে।

৩. whenComplete() ব্যবহার করে পরবর্তী কাজ পরিচালনা

import java.util.concurrent.CompletableFuture;

public class WhenCompleteExample {
    public static void main(String[] args) {
        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            if (true) {
                throw new RuntimeException("Error occurred!");
            }
            return "Success";
        }).whenComplete((result, ex) -> {
            if (ex != null) {
                System.out.println("Completed with Exception: " + ex.getMessage());
            } else {
                System.out.println("Completed Successfully: " + result);
            }
        });

        future.join();
    }
}

ব্যাখ্যা:

  • whenComplete(): কাজ সম্পন্ন হওয়ার পরে ব্যতিক্রম বা স্বাভাবিক ফলাফল পরিচালনা করে।
  • এটি শুধুমাত্র ফলাফল বা ব্যতিক্রম লগ করতে ব্যবহার করা হয়।
  1. Combining Multiple Futures:
    • thenCombine(): দুটি Future এর ফলাফল একত্র করে।
    • allOf(): সব Future একত্র করে কাজ সম্পন্ন হলে চলায়।
    • anyOf(): প্রথম সম্পন্ন হওয়া Future থেকে ফলাফল প্রদান করে।
  2. Exception Handling:
    • exceptionally(): ব্যতিক্রমের সময় বিকল্প ফলাফল প্রদান করে।
    • handle(): ব্যতিক্রম এবং স্বাভাবিক ফলাফল উভয় পরিচালনা করে।
    • whenComplete(): কাজের শেষে ফলাফল বা ব্যতিক্রম পরিচালনা করে।

এই ফিচারগুলো ব্যবহার করে জাভাতে অ্যাসিঙ্ক্রোনাস প্রোগ্রামিং আরও সহজ, কার্যকর এবং স্থিতিশীল করা যায়।

Content added By
Promotion