CompletableFuture হল Java 8-এ java.util.concurrent প্যাকেজে অন্তর্ভুক্ত একটি ক্লাস যা অ্যাসিনক্রোনাস প্রোগ্রামিং সহজ এবং কার্যকরী করার জন্য ব্যবহৃত হয়। এটি Future ইন্টারফেসের একটি উন্নত সংস্করণ এবং অ্যাসিনক্রোনাস অপারেশন পরিচালনা করার জন্য আরও বেশি ক্ষমতা এবং নমনীয়তা প্রদান করে। CompletableFuture আপনাকে এমন কাজগুলি সম্পন্ন করতে সাহায্য করে যা সম্পূর্ণ হওয়ার জন্য অপেক্ষা করতে না করে একযোগভাবে (concurrently) সম্পন্ন হতে পারে।
CompletableFuture-এর সাহায্যে আপনি একাধিক অ্যাসিনক্রোনাস কাজকে চেইন (chaining) করতে পারেন এবং একাধিক কাজের ফলাফল সমন্বিতভাবে (combine) পেতে পারেন।
CompletableFuture-এর সুবিধা
- অ্যাসিনক্রোনাস কাজের সহজ সমাধান: এটি অ্যাসিনক্রোনাস কাজের জন্য সোজা এবং কার্যকরী সমাধান প্রদান করে।
- ফিউচার চেইনিং: এটি একাধিক অ্যাসিনক্রোনাস কাজকে চেইনিং করে চালানোর সুযোগ দেয়।
- পারফরম্যান্স বৃদ্ধি: এটি থ্রেড ব্যবস্থাপনাকে সহজ করে এবং অ্যাসিনক্রোনাস অপারেশনগুলো একে অপরের সাথে সমন্বিতভাবে চালাতে সাহায্য করে।
- ভুল ব্যবস্থাপনা: এটি ত্রুটির ক্ষেত্রে উন্নত সমাধান সরবরাহ করে এবং কোডে
try-catchব্লক সংযোজনের দরকার হয় না।
CompletableFuture ক্লাসের প্রধান পদ্ধতি
- supplyAsync(): একটি অ্যাসিনক্রোনাস কাজের জন্য ফলাফল প্রদান করতে ব্যবহার করা হয়।
- thenApply(): একটি অ্যাসিনক্রোনাস কাজের পরবর্তী কাজ করতে ব্যবহৃত হয় (চেইনিং)।
- thenAccept(): ফলাফল গ্রহণ করে এবং প্রক্রিয়াজাত করে (কেবল সাইড এফেক্ট জন্য)।
- thenCombine(): দুটি
CompletableFutureএর ফলাফল একত্রিত করতে ব্যবহার করা হয়। - exceptionally(): কোনো ত্রুটি থাকলে তাকে হ্যান্ডল করার জন্য ব্যবহৃত হয়।
- get(): কাজ সম্পন্ন হলে ফলাফল ফিরে পাওয়ার জন্য ব্যবহৃত হয়।
CompletableFuture ব্যবহার করার উদাহরণ
উদাহরণ ১: অ্যাসিনক্রোনাস কাজের জন্য supplyAsync() ব্যবহার
import java.util.concurrent.CompletableFuture;
public class CompletableFutureExample {
public static void main(String[] args) {
// supplyAsync() ব্যবহার করে অ্যাসিনক্রোনাস কাজ সম্পাদন
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(2000); // সিমুলেটেড কাজের জন্য দেরি
} catch (InterruptedException e) {
e.printStackTrace();
}
return 42;
});
// get() ব্যবহার করে ফলাফল গ্রহণ করা (এইখানে সিঙ্ক্রোনাসভাবে অপেক্ষা করা হবে)
future.thenAccept(result -> System.out.println("Result: " + result)); // Output: Result: 42
}
}এখানে, supplyAsync() একটি অ্যাসিনক্রোনাস কাজ শুরু করে এবং thenAccept() এর মাধ্যমে কাজের ফলাফল প্রিন্ট করা হয়।
উদাহরণ ২: thenApply() ব্যবহার করে ফলাফল চেইনিং
import java.util.concurrent.CompletableFuture;
public class CompletableFutureExample {
public static void main(String[] args) {
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
return 5;
});
// thenApply() ব্যবহার করে অ্যাসিনক্রোনাস কাজের পরবর্তী কাজ করা
future.thenApply(result -> result * 2)
.thenAccept(result -> System.out.println("Processed Result: " + result)); // Output: Processed Result: 10
}
}এখানে, thenApply() ব্যবহার করে প্রথম কাজের ফলাফলকে দুগুণ করা হয়েছে এবং thenAccept() দ্বারা প্রক্রিয়াজাত ফলাফল প্রিন্ট করা হয়েছে।
উদাহরণ ৩: exceptionHandling() ব্যবহার করে ত্রুটি হ্যান্ডলিং
import java.util.concurrent.CompletableFuture;
public class CompletableFutureExample {
public static void main(String[] args) {
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
if (true) { // সিমুলেটেড ত্রুটি
throw new RuntimeException("Something went wrong!");
}
return 42;
});
future.exceptionally(ex -> {
System.out.println("Handled Exception: " + ex.getMessage()); // Output: Handled Exception: Something went wrong!
return 0; // Default Value in case of Exception
}).thenAccept(result -> System.out.println("Result: " + result)); // Output: Result: 0
}
}এখানে, exceptionally() ব্যবহার করে অ্যাসিনক্রোনাস কাজের সময় ঘটে যাওয়া ত্রুটিকে হ্যান্ডল করা হয়েছে।
উদাহরণ ৪: thenCombine() ব্যবহার করে দুইটি CompletableFuture এর ফলাফল একত্রিত করা
import java.util.concurrent.CompletableFuture;
public class CompletableFutureExample {
public static void main(String[] args) {
CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> 10);
CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> 20);
// thenCombine() ব্যবহার করে দুটি CompletableFuture এর ফলাফল একত্রিত করা
future1.thenCombine(future2, (result1, result2) -> result1 + result2)
.thenAccept(result -> System.out.println("Combined Result: " + result)); // Output: Combined Result: 30
}
}এখানে, দুটি আলাদা CompletableFuture এর ফলাফলকে thenCombine() ব্যবহার করে একত্রিত করা হয়েছে।
CompletableFuture এর সুবিধা
- অ্যাসিনক্রোনাস এবং প্যারালেল অপারেশন:
- এটি একাধিক কাজের ফলাফল পাবার জন্য অ্যাসিনক্রোনাসভাবে কাজ করে এবং সেগুলোর উপর অপারেশন করতে পারে।
- ফাংশনাল চেইনিং:
- আপনি একাধিক অ্যাসিনক্রোনাস কাজ চেইন করতে পারেন এবং বিভিন্ন ধরনের ফাংশনাল প্রোগ্রামিং স্টাইল ব্যবহার করতে পারেন, যেমন
thenApply(),thenCombine(),thenAccept()ইত্যাদি।
- আপনি একাধিক অ্যাসিনক্রোনাস কাজ চেইন করতে পারেন এবং বিভিন্ন ধরনের ফাংশনাল প্রোগ্রামিং স্টাইল ব্যবহার করতে পারেন, যেমন
- Exception Handling:
CompletableFutureত্রুটি হ্যান্ডলিংকে খুব সহজ করে তোলে।exceptionally()মেথড ব্যবহার করে আপনি যেকোনো ত্রুটি ম্যানেজ করতে পারেন।
- বিভিন্ন কাজের সমন্বয়:
- একাধিক অ্যাসিনক্রোনাস কাজের ফলাফল সমন্বিত করতে
thenCombine(),allOf(),anyOf()ইত্যাদি মেথডগুলো ব্যবহার করা যেতে পারে।
- একাধিক অ্যাসিনক্রোনাস কাজের ফলাফল সমন্বিত করতে
সারসংক্ষেপ
CompletableFuture Java 8-এর একটি শক্তিশালী টুল যা অ্যাসিনক্রোনাস কাজ এবং মাল্টিথ্রেডিং সমাধান সহজ করে তোলে। এটি আপনাকে একাধিক কাজের উপর একযোগভাবে কাজ করতে সহায়ক, এবং ফলস্বরূপ আপনার অ্যাপ্লিকেশনের পারফরম্যান্স এবং স্কেলেবিলিটি বৃদ্ধি পায়। CompletableFuture ক্লাস বিভিন্ন মেথড যেমন thenApply(), thenAccept(), exceptionally(), এবং thenCombine() ব্যবহার করে কাজের ফলাফল পরিচালনা এবং ফাংশনাল স্টাইল চেইনিং করা সম্ভব করে তোলে।
CompletableFuture Java 8 এর java.util.concurrent প্যাকেজে অন্তর্ভুক্ত একটি ক্লাস, যা অ্যাসিনক্রোনাস প্রোগ্রামিং এবং non-blocking কার্যকারিতা প্রদান করে। এটি একটি ফিউচার (Future) অবজেক্টের উন্নত সংস্করণ যা আপনাকে asynchronous computation পরিচালনা করতে সক্ষম করে।
এটি অ্যাসিনক্রোনাস (একা সময়) অপারেশনগুলি একত্রিত (combine) এবং সহজভাবে ম্যানেজ করতে সাহায্য করে। Java এর আগের Future ইন্টারফেসের তুলনায় CompletableFuture অনেক বেশি ফিচার সমর্থন করে এবং কার্যকরীভাবে কোড লেখার সুবিধা দেয়।
CompletableFuture এর মৌলিক ধারণা
CompletableFuture একটি Future অবজেক্ট যা completing (সম্পন্ন করা) প্রক্রিয়া আরও সহজ করে। এটি ফিউচার রেজাল্ট হিসাবেও কাজ করে, অর্থাৎ এটি আসন্ন কোনো ফলাফল যা ভবিষ্যতে পাওয়া যাবে, তবে চলমান কাজে কিছু সময় নিতে পারে। CompletableFuture এর সবচেয়ে গুরুত্বপূর্ণ বৈশিষ্ট্য হল, এটি asynchronous অপারেশনকে সমর্থন করে এবং আপনি যখন পুরো অপারেশনটি শেষ করতে চান তখন এর উপর কিছু ফাংশন বা কার্যকলাপ অ্যাপ্লাই করতে পারেন।
CompletableFuture এর মাধ্যমে:
- অ্যাসিনক্রোনাস অপারেশন চালানো যায়।
- কমপ্লেক্স অ্যাসিনক্রোনাস চেইনিং করা যায়।
- non-blocking কার্যকলাপ পরিচালনা করা যায়।
CompletableFuture এর তৈরি করার উপায়
CompletableFuture তৈরি করার জন্য কয়েকটি পদ্ধতি রয়েছে। আপনি এটি সরাসরি নতুন করে তৈরি করতে পারেন বা অ্যাসিনক্রোনাস অপারেশন থেকে শুরু করতে পারেন।
১. supplyAsync() মেথড দ্বারা
এটি একটি নতুন অ্যাসিনক্রোনাস অপারেশন শুরু করে এবং একটি ফলাফল (যেমন একটি অ্যাসিনক্রোনাস কাজের জন্য কোন মান) ফেরত দেয়।
import java.util.concurrent.CompletableFuture;
public class CompletableFutureExample {
public static void main(String[] args) {
// Asynchronous task with supplyAsync
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(1000); // Simulating delay
} catch (InterruptedException e) {
e.printStackTrace();
}
return 42; // Returning a result
});
// Use the result when it's ready
future.thenAccept(result -> System.out.println("Result: " + result)); // Output: Result: 42
}
}এখানে, supplyAsync() একটি অ্যাসিনক্রোনাস কাজ শুরু করে এবং 1000 মিলিসেকেন্ড পর 42 মানটি ফিরিয়ে দেয়।
২. runAsync() মেথড দ্বারা
এটি অ্যাসিনক্রোনাস কাজ শুরু করে, তবে এটি কোনো ফলাফল ফিরিয়ে দেয় না।
import java.util.concurrent.CompletableFuture;
public class CompletableFutureExample {
public static void main(String[] args) {
// Asynchronous task without returning a result
CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
try {
Thread.sleep(1000); // Simulating a task
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Task completed");
});
// Wait for the task to complete
future.join(); // Blocks until the task is completed
}
}এখানে, runAsync() একটি অ্যাসিনক্রোনাস কাজ শুরু করে, কিন্তু কোনো মান ফিরিয়ে দেয় না। এটি শুধুমাত্র কাজ সম্পন্ন হলে একটি বার্তা প্রদর্শন করে।
CompletableFuture এর ব্যবহার এবং কার্যকারিতা
১. thenApply() এবং thenAccept()
thenApply() এবং thenAccept() আপনাকে ফিউচার কাজের উপর পরবর্তী স্টেপ যোগ করতে সহায়তা করে। এগুলি ফাংশনাল প্রোগ্রামিং স্টাইলের মতো, যেখানে আপনি একটি ফাংশন পরপর একাধিক কাজে প্রয়োগ করতে পারেন।
thenApply(): একটি ফলাফল নিয়ে পরবর্তী অপারেশন করার জন্য ব্যবহার হয়।thenAccept(): একটি ফলাফল গ্রহণ করে একটি সাইড-এফেক্ট তৈরি করে (যেমন, প্রিন্ট বা লগ)।
উদাহরণ:
import java.util.concurrent.CompletableFuture;
public class CompletableFutureExample {
public static void main(String[] args) {
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
return 10;
});
future.thenApply(result -> result * 2) // Multiply the result by 2
.thenAccept(result -> System.out.println("Final result: " + result)); // Output: Final result: 20
}
}এখানে, প্রথমে একটি অ্যাসিনক্রোনাস কাজ (10 রিটার্ন) শুরু করা হয়েছে, তারপর thenApply() এর মাধ্যমে মানটি 2 গুণ বাড়ানো হয়েছে এবং অবশেষে thenAccept() এর মাধ্যমে ফলাফল প্রিন্ট করা হয়েছে।
২. thenCombine()
thenCombine() মেথডটি দুটি CompletableFuture কে একত্রে (combine) একটি একক ফলাফলে রূপান্তর করতে ব্যবহৃত হয়।
import java.util.concurrent.CompletableFuture;
public class CompletableFutureExample {
public static void main(String[] args) {
CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> 5);
CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> 10);
future1.thenCombine(future2, (result1, result2) -> result1 + result2)
.thenAccept(result -> System.out.println("Combined result: " + result)); // Output: Combined result: 15
}
}এখানে, দুটি অ্যাসিনক্রোনাস কাজের ফলাফল একত্রিত (combine) হয়ে 15 হিসেবে প্রিন্ট করা হয়েছে।
৩. exceptionally()
exceptionally() ব্যবহার করে আপনি একটি এক্সেপশন হ্যান্ডলার অ্যাসাইন করতে পারেন, যা কোনো ত্রুটি (exception) ঘটলে একটি ডিফল্ট মান প্রদান করবে।
import java.util.concurrent.CompletableFuture;
public class CompletableFutureExample {
public static void main(String[] args) {
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
throw new RuntimeException("Something went wrong");
});
future.exceptionally(ex -> {
System.out.println("Exception: " + ex.getMessage());
return 0; // Default value in case of exception
}).thenAccept(result -> System.out.println("Result: " + result)); // Output: Exception: Something went wrong, Result: 0
}
}এখানে, exceptionally() মেথডটি ত্রুটি ঘটলে একটি ডিফল্ট মান 0 ফেরত দিয়েছে।
CompletableFuture এর বিশেষ বৈশিষ্ট্য
- Non-blocking I/O:
CompletableFutureব্যবহার করে I/O অপারেশনগুলিকে non-blockingভাবে পরিচালনা করা যায়। এতে কোনো থ্রেড ব্লক হয় না এবং অন্যান্য কাজ চলতে থাকে। - Composing Asynchronous Tasks: একাধিক অ্যাসিনক্রোনাস কাজকে চেইন আকারে সংযুক্ত করা যায়।
- Concurrency: একাধিক অ্যাসিনক্রোনাস কাজকে প্যারালালভাবে চালানো যায়।
- Exception Handling:
CompletableFuture-এ অ্যাসিনক্রোনাস কাজের জন্য এক্সেপশন হ্যান্ডলিং সহজ করে দেওয়া হয়েছে।
সারসংক্ষেপ
CompletableFuture Java 8-এ অ্যাসিনক্রোনাস প্রোগ্রামিংকে আরও সহজ এবং কার্যকরী করে তোলে। এটি আপনাকে:
- Asynchronous computation পরিচালনা করতে সহায়তা করে।
- একাধিক কাজের ফলাফল একত্রে (combine) করতে পারে।
- একটি ফলাফল পেতে ব্লক না করে (non-blocking) কাজ করতে পারে।
- ফলাফলের সাথে প্রক্রিয়া যোগ করতে বা এক্সেপশন হ্যান্ডলিং করতে সহায়তা করে।
এটি Java concurrency এবং parallel programming এর জন্য একটি শক্তিশালী টুল হিসেবে ব্যবহৃত হচ্ছে, বিশেষ করে যেখানে বড় পরিমাণের কাজ দ্রুত সম্পন্ন করতে হয়।
Java 8-এ CompletableFuture ক্লাসটি Asynchronous Programming বা non-blocking I/O operations পরিচালনার জন্য একটি শক্তিশালী টুল হিসেবে যোগ করা হয়েছে। এটি Future ইন্টারফেসের একটি উন্নত সংস্করণ, যা asynchronous বা parallel tasks সহজে পরিচালনা করতে সহায়তা করে।
CompletableFuture ব্যবহার করে আপনি asynchronous tasks একত্রে কাজ করাতে পারেন, বিভিন্ন কাজের মধ্যে নির্দিষ্ট সময়ের জন্য অপেক্ষা না করে। এতে অ্যাসিঙ্ক্রোনাস কোডের মধ্যে callback বা chaining তৈরি করা সম্ভব।
Asynchronous Tasks এবং CompletableFuture
Asynchronous tasks হল সেই কাজগুলি যা ব্যাকগ্রাউন্ডে চলতে থাকে এবং তারা প্রধান থ্রেড (main thread) বা অন্যান্য কাজগুলির সাথে সমান্তরালে সম্পাদিত হয়। Java-তে, সিঙ্ক্রোনাস কাজের পরিবর্তে অ্যাসিঙ্ক্রোনাস কাজগুলি পরিচালনা করার জন্য CompletableFuture খুবই কার্যকরী।
CompletableFuture দিয়ে আপনি:
- একাধিক অ্যাসিঙ্ক্রোনাস কাজ সমান্তরালে চালাতে পারেন
- কাজগুলো শেষ হওয়ার পর ফলাফল প্রাপ্তির জন্য callback তৈরি করতে পারেন
- অ্যাসিঙ্ক্রোনাস কাজের exception handling করতে পারেন
CompletableFuture এর মেথডসমূহ
supplyAsync(): একটি অ্যাসিঙ্ক্রোনাস কাজ শুরু করে, এবং এটি একটিCompletableFutureরিটার্ন করে।thenApply(): কোনোCompletableFutureথেকে প্রাপ্ত ফলাফল পরবর্তী অপারেশন বা মানে রূপান্তর করতে ব্যবহৃত হয়।thenAccept(): প্রাপ্ত ফলাফলের উপর কোনো কার্যক্রম করতে ব্যবহৃত হয়, কিন্তু ফলাফল রিটার্ন করে না।thenCombine(): দুটি পৃথকCompletableFutureএর ফলাফল একত্রিত করতে ব্যবহৃত হয়।allOf(): একাধিকCompletableFutureএর সমাপ্তির জন্য অপেক্ষা করতে ব্যবহৃত হয়।exceptionally(): কোনো exception ঘটলে তা হ্যান্ডেল করতে ব্যবহৃত হয়।
CompletableFuture এর মাধ্যমে Asynchronous Tasks পরিচালনা
উদাহরণ ১: supplyAsync() ব্যবহার
import java.util.concurrent.CompletableFuture;
public class CompletableFutureExample {
public static void main(String[] args) {
// Start asynchronous task
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(2000); // Simulate long running task
} catch (InterruptedException e) {
e.printStackTrace();
}
return 10;
});
// Continue working without blocking
System.out.println("Main thread continues working...");
// Wait for the result and print
future.thenAccept(result -> System.out.println("Result: " + result));
}
}এখানে, supplyAsync() একটি অ্যাসিঙ্ক্রোনাস কাজ শুরু করে এবং ব্যাকগ্রাউন্ডে 2 সেকেন্ডের জন্য স্লিপ করে (এটি একটি লম্বা কাজের মতো)। Main thread ব্লক না হয়ে, অন্যান্য কাজ চালিয়ে যায় এবং পরবর্তী স্টেপে ফলাফলটি প্রিন্ট করা হয়।
উদাহরণ ২: thenApply() ব্যবহার
import java.util.concurrent.CompletableFuture;
public class CompletableFutureExample {
public static void main(String[] args) {
// Asynchronous task to get a number
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> 10);
// Chaining another asynchronous operation on the result
future.thenApply(result -> result * 2) // Multiply result by 2
.thenAccept(finalResult -> System.out.println("Final result: " + finalResult)); // Output: 20
}
}এখানে, প্রথমে CompletableFuture.supplyAsync() মেথডে 10 পাওয়া যাচ্ছে এবং তারপর thenApply() ব্যবহার করে সেই মানকে দ্বিগুণ করা হচ্ছে। thenAccept() মেথড ব্যবহার করে শেষের ফলাফলটি আউটপুট করা হয়েছে।
উদাহরণ ৩: thenCombine() ব্যবহার
thenCombine() দুটি আলাদা CompletableFuture এর ফলাফল একত্রিত করতে ব্যবহৃত হয়।
import java.util.concurrent.CompletableFuture;
public class CompletableFutureExample {
public static void main(String[] args) {
// Asynchronous task 1
CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> 10);
// Asynchronous task 2
CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> 20);
// Combine both results
CompletableFuture<Integer> combinedFuture = future1.thenCombine(future2, (result1, result2) -> result1 + result2);
// Print the result
combinedFuture.thenAccept(result -> System.out.println("Combined result: " + result)); // Output: Combined result: 30
}
}এখানে, দুটি অ্যাসিঙ্ক্রোনাস কাজের ফলাফল একত্রিত করা হয়েছে এবং তারপর thenAccept() মেথড দিয়ে ফলাফল প্রিন্ট করা হয়েছে।
উদাহরণ ৪: allOf() ব্যবহার
allOf() মেথড একাধিক CompletableFuture এর সমাপ্তির জন্য অপেক্ষা করে।
import java.util.concurrent.CompletableFuture;
public class CompletableFutureExample {
public static void main(String[] args) {
// Asynchronous tasks
CompletableFuture<Void> future1 = CompletableFuture.supplyAsync(() -> {
try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); }
return "Task 1 Completed";
}).thenAccept(System.out::println);
CompletableFuture<Void> future2 = CompletableFuture.supplyAsync(() -> {
try { Thread.sleep(1500); } catch (InterruptedException e) { e.printStackTrace(); }
return "Task 2 Completed";
}).thenAccept(System.out::println);
// Wait for all tasks to complete
CompletableFuture<Void> allOfFuture = CompletableFuture.allOf(future1, future2);
allOfFuture.join(); // Blocking wait for both futures to finish
System.out.println("All tasks completed.");
}
}এখানে, allOf() মেথডটি ব্যবহার করে দুটি অ্যাসিঙ্ক্রোনাস কাজের জন্য অপেক্ষা করা হয়েছে এবং একবার সব কাজ শেষ হলে একটি মেসেজ প্রিন্ট করা হয়েছে।
CompletableFuture এর মধ্যে Exception Handling
যেহেতু অ্যাসিঙ্ক্রোনাস কোডে ব্যতিক্রম ঘটতে পারে, সেক্ষেত্রে exceptionally() মেথড ব্যবহার করে exception handling করা সম্ভব।
import java.util.concurrent.CompletableFuture;
public class CompletableFutureExample {
public static void main(String[] args) {
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
if (true) throw new RuntimeException("Something went wrong!");
return 10;
});
future.exceptionally(ex -> {
System.out.println("Exception: " + ex.getMessage());
return 0; // Default value
}).thenAccept(result -> System.out.println("Result: " + result));
}
}এখানে, exceptionally() মেথডটি ব্যবহার করে কোনো ব্যতিক্রম ঘটলে তা হ্যান্ডেল করা হয়েছে এবং ডিফল্ট মান 0 রিটার্ন করা হয়েছে।
সারসংক্ষেপ
- CompletableFuture Java-তে অ্যাসিঙ্ক্রোনাস প্রোগ্রামিং সহজ করে এবং non-blocking কাজের জন্য একটি শক্তিশালী টুল।
- এটি
supplyAsync(),thenApply(),thenAccept(),allOf()ইত্যাদি মেথড সরবরাহ করে যা একাধিক অ্যাসিঙ্ক্রোনাস কাজ সমান্তরালে বা একে অপরের সাথে চেইন করতে সহায়তা করে। - Exception Handling এবং callback functions এর মাধ্যমে অ্যাসিঙ্ক্রোনাস কোড আরও কার্যকরী এবং স্থিতিশীল করা যায়।
CompletableFuture Java-তে অ্যাসিঙ্ক্রোনাস কাজগুলি সহজ ও কার্যকরভাবে পরিচালনার জন্য একটি অন্যতম উপায়।
Java 8-এ CompletableFuture ক্লাসটি অ্যাসিঙ্ক্রোনাস কম্পিউটেশন এবং তার ফলাফল পরিচালনার জন্য ব্যবহৃত হয়। যখন একাধিক অ্যাসিঙ্ক্রোনাস অপারেশন একত্রিত করা প্রয়োজন, তখন thenApply(), thenAccept(), এবং thenCompose() অত্যন্ত কার্যকরী মেথড। এগুলো আপনাকে অ্যাসিঙ্ক্রোনাস টাস্কের ফলাফল সঠিকভাবে প্রক্রিয়া করতে এবং বিভিন্ন অ্যাসিঙ্ক্রোনাস অপারেশন একসাথে পরিচালনা করতে সহায়তা করে।
এখানে প্রতিটি মেথডের ব্যাখ্যা এবং উদাহরণ দেওয়া হলো।
১. thenApply()
thenApply() মেথডটি CompletableFuture এর ফলাফল গ্রহণ করে এবং একটি ট্রান্সফরমেশন ফাংশন প্রয়োগ করে নতুন একটি CompletableFuture তৈরি করে। এটি মূলত কোন ফিউচার এর ফলাফলকে পরিবর্তন করতে ব্যবহৃত হয়।
- ব্যবহার: আপনি যদি একটি ফিউচারের ফলাফল নিয়ে কোন কিছু পরিবর্তন করতে চান এবং তারপরে নতুন ফিউচার পেতে চান, তখন
thenApply()ব্যবহার করতে হবে।
thenApply() উদাহরণ:
import java.util.concurrent.CompletableFuture;
public class ThenApplyExample {
public static void main(String[] args) {
// একটি CompletableFuture তৈরি
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> 5);
// thenApply() ব্যবহার করে ফলাফল ট্রান্সফর্ম করা
CompletableFuture<Integer> transformedFuture = future.thenApply(result -> result * 2);
// transformedFuture থেকে ফলাফল নেয়া
transformedFuture.thenAccept(result -> System.out.println("Transformed result: " + result));
}
}ব্যাখ্যা:
CompletableFuture.supplyAsync()একটি অ্যাসিঙ্ক্রোনাস অপারেশন তৈরি করে যা5মান প্রদান করবে।thenApply()ফাংশনটি ফিউচারের ফলাফলকে* 2করে পরিবর্তন করবে।thenAccept()এটি প্রিন্ট করবে:Transformed result: 10।
Output:
Transformed result: 10২. thenAccept()
thenAccept() মেথডটি CompletableFuture এর ফলাফল গ্রহণ করে এবং তা সাইড-এফেক্ট হিসেবে ব্যবহার করে। এই মেথডটি কোন নতুন CompletableFuture ফেরত দেয় না, এটি শুধুমাত্র ফলাফল ব্যবহারের উদ্দেশ্যে।
- ব্যবহার: যখন আপনি শুধুমাত্র ফলাফলকে গ্রহণ করে কোন সাইড-এফেক্ট (যেমন প্রিন্ট, লগ করা) তৈরি করতে চান, তখন
thenAccept()ব্যবহার করবেন।
thenAccept() উদাহরণ:
import java.util.concurrent.CompletableFuture;
public class ThenAcceptExample {
public static void main(String[] args) {
// একটি CompletableFuture তৈরি
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> 100);
// thenAccept() ব্যবহার করে ফলাফল গ্রহন করা এবং প্রিন্ট করা
future.thenAccept(result -> System.out.println("Consumed result: " + result));
}
}ব্যাখ্যা:
CompletableFuture.supplyAsync()একটি অ্যাসিঙ্ক্রোনাস অপারেশন তৈরি করে যা100প্রদান করবে।thenAccept()ফলাফল গ্রহণ করবে এবং প্রিন্ট করবে:Consumed result: 100।
Output:
Consumed result: 100৩. thenCompose()
thenCompose() মেথডটি একাধিক অ্যাসিঙ্ক্রোনাস অপারেশন একত্রিত করতে ব্যবহৃত হয়, যেখানে দ্বিতীয় অ্যাসিঙ্ক্রোনাস অপারেশনটির ফলাফল প্রথম অপারেশনের ফলাফল দিয়ে শুরু হয়। এটি সাধারণত একাধিক স্টেপের অ্যাসিঙ্ক্রোনাস অপারেশন চেইন করার জন্য ব্যবহৃত হয়।
- ব্যবহার: যখন আপনি একটি ফিউচারের ফলামের উপর ভিত্তি করে আরেকটি নতুন অ্যাসিঙ্ক্রোনাস অপারেশন শুরু করতে চান, তখন
thenCompose()ব্যবহার করবেন।
thenCompose() উদাহরণ:
import java.util.concurrent.CompletableFuture;
public class ThenComposeExample {
public static void main(String[] args) {
// একটি CompletableFuture তৈরি
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> 5);
// thenCompose() ব্যবহার করে আরও একটি অ্যাসিঙ্ক্রোনাস কাজ
CompletableFuture<Integer> finalResult = future.thenCompose(result ->
CompletableFuture.supplyAsync(() -> result * 2)
);
// finalResult থেকে ফলাফল নেয়া
finalResult.thenAccept(result -> System.out.println("Final result: " + result));
}
}ব্যাখ্যা:
CompletableFuture.supplyAsync()একটি অ্যাসিঙ্ক্রোনাস অপারেশন তৈরি করে যা5প্রদান করবে।thenCompose()আরেকটি অ্যাসিঙ্ক্রোনাস অপারেশন (যা5 * 2করবে) চালাবে।thenAccept()চূড়ান্ত ফলাফলটি প্রিন্ট করবে:Final result: 10।
Output:
Final result: 10Key Differences Between thenApply(), thenAccept(), and thenCompose()
| Method | Use Case | Returns New CompletableFuture? | Example Use Case |
|---|---|---|---|
thenApply() | যখন আপনি একটি ফিউচারের ফলাফলকে পরিবর্তন করতে চান। | Yes | ফলাফল পরিবর্তন করে নতুন ফিউচার তৈরি করা (যেমন, ২ গুণ করা) |
thenAccept() | যখন আপনি শুধুমাত্র ফলাফল গ্রহণ করে কোন সাইড-এফেক্ট করতে চান। | No | ফলাফল প্রিন্ট বা লগ করা |
thenCompose() | যখন আপনি একাধিক অ্যাসিঙ্ক্রোনাস অপারেশন চেইন করতে চান। | Yes | একাধিক অ্যাসিঙ্ক্রোনাস কাজের মধ্যে একটির ফলাফল দিয়ে পরবর্তী কাজ শুরু করা |
Conclusion
thenApply(): যখন আপনি ফিউচারের ফলাফলকে পরিবর্তন করতে চান।thenAccept(): যখন আপনি শুধুমাত্র ফলাফল গ্রহণ করে কোনো সাইড-এফেক্ট (যেমন প্রিন্ট, লগ) করতে চান।thenCompose(): যখন আপনি একাধিক অ্যাসিঙ্ক্রোনাস অপারেশন চেইন করতে চান, যেখানে পরবর্তী অপারেশন প্রথমটির ফলাফলের উপর নির্ভর করে।
এই তিনটি মেথডই CompletableFuture এর মাধ্যমে অ্যাসিঙ্ক্রোনাস অপারেশনগুলিকে আরও কার্যকরভাবে পরিচালনা করতে সাহায্য করে।
Java 8 থেকে CompletableFuture একটি অত্যন্ত শক্তিশালী ক্লাস হিসেবে যুক্ত হয়েছে, যা asynchronous programming-এর জন্য ব্যবহৃত হয়। CompletableFuture হ'ল Future এর একটি উন্নত সংস্করণ, যা আপনাকে একাধিক থ্রেডে কাজ করে এবং ভবিষ্যতে কোনো মান (value) প্রাপ্তির জন্য অপেক্ষা করতে সাহায্য করে। এটি Java 8 এর java.util.concurrent প্যাকেজে অন্তর্ভুক্ত।
একটি গুরুত্বপূর্ণ দিক হল exception handling-এর মাধ্যমে CompletableFuture তে asynchronous কাজের ফলাফল প্রাপ্তির সময় exception বা error সঠিকভাবে হ্যান্ডল করা। এই ফিচারটি অ্যাসিঙ্ক্রোনাস প্রসেসে error recovery সহজ করে।
CompletableFuture এর মাধ্যমে Asynchronous Programming
CompletableFuture হল Future এর একটি উন্নত সংস্করণ, যা CompletableFuture.complete() মেথড ব্যবহার করে আপনার অ্যাসিঙ্ক্রোনাস কাজগুলিকে সমাপ্ত করতে সাহায্য করে এবং একটি ফলাফল বা exception প্রাপ্তি নির্ধারণ করে।
১. CompletableFuture এর মূল ব্যবহার
CompletableFuture সাধারণত supplyAsync(), runAsync() এবং thenApply(), thenAccept(), thenRun() ইত্যাদি মেথড ব্যবহার করে কাজ করে।
উদাহরণ: CompletableFuture basic example
import java.util.concurrent.CompletableFuture;
public class CompletableFutureExample {
public static void main(String[] args) {
// supplyAsync() ব্যবহার করে অ্যাসিঙ্ক্রোনাস কাজ
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
return 5 * 5; // 25 হবে
});
// thenApply() ব্যবহার করে ফলাফল প্রক্রিয়া করা
future.thenApply(result -> {
return result + 10; // 25 + 10 = 35
}).thenAccept(result -> {
System.out.println("Final Result: " + result); // Output: Final Result: 35
});
}
}এখানে, supplyAsync() একটি অ্যাসিঙ্ক্রোনাস কাজ চালায় এবং thenApply() এবং thenAccept() মেথডগুলির মাধ্যমে সেই কাজের ফলাফল প্রক্রিয়া করা হয়েছে।
২. Exception Handling with CompletableFuture
Java 8 এর CompletableFuture exception handling এর জন্য exceptionally(), handle() এবং whenComplete() মেথড প্রদান করেছে, যা অ্যাসিঙ্ক্রোনাস কাজের সময় exceptions হ্যান্ডেল করতে সহায়ক।
exceptionally():
exceptionally() মেথডটি exception ঘটলে একটি fallback (ডিফল্ট) মান প্রদান করে।
handle():
handle() মেথডটি success এবং failure উভয় ক্ষেত্রেই ব্যবহৃত হয় এবং এটি একটি BiFunction নেয় যা result এবং exception উভয়ই গ্রহণ করতে পারে।
whenComplete():
whenComplete() মেথডটি কাজ শেষ হওয়ার পরে, সফল বা ব্যর্থ হওয়ার পর কলব্যাক হিসেবে ব্যবহৃত হয়, কিন্তু এটি exception হ্যান্ডলিং করে না।
৩. Exception Handling Example
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
public class CompletableFutureExceptionHandling {
public static void main(String[] args) {
// একটি CompletableFuture তৈরি করা
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
if (true) {
throw new RuntimeException("Something went wrong!");
}
return 50;
});
// exceptionally() দিয়ে exception handle করা
future = future.exceptionally(ex -> {
System.out.println("Exception caught: " + ex.getMessage());
return 0; // fallback value
});
// ফলাফল প্রাপ্তি
try {
System.out.println("Final Result: " + future.get()); // Output: Exception caught: Something went wrong! Final Result: 0
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
}এখানে exceptionally() ব্যবহার করা হয়েছে, যা exception ঘটলে একটি fallback মান প্রদান করেছে। যদি কোনও exception ঘটত, তবে 0 মানটি ফলস্বরূপ প্রাপ্ত হত।
৪. handle() Method for Exception Handling
handle() মেথডটি success এবং failure উভয় ক্ষেত্রেই কাজ করে এবং এটি একটি BiFunction নেয় যা একটি সফল ফলাফল অথবা exception গ্রহণ করতে পারে। এটি একটি Optional ফলাফল প্রদান করে, যাতে exception উপস্থিত থাকলে সেটি মোকাবেলা করা যায়।
উদাহরণ: handle() Exception Handling
import java.util.concurrent.CompletableFuture;
public class CompletableFutureHandleExample {
public static void main(String[] args) {
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
if (true) {
throw new RuntimeException("Error occurred!");
}
return 100;
});
// handle() মেথড ব্যবহার করে exception এবং result একসাথে handle করা
future.handle((result, ex) -> {
if (ex != null) {
System.out.println("Exception handled: " + ex.getMessage());
return 0; // return fallback value
} else {
return result;
}
}).thenAccept(result -> {
System.out.println("Result: " + result); // Output: Exception handled: Error occurred! Result: 0
});
}
}এখানে, handle() মেথড ব্যবহার করা হয়েছে, যা exception এর ক্ষেত্রে fallback ভ্যালু প্রদান করেছে এবং সফলভাবে প্রাপ্ত ফলাফলটি প্রিন্ট করেছে।
৫. whenComplete() Method for Exception Handling
whenComplete() মেথডটি success এবং failure উভয় ক্ষেত্রেই কলব্যাক হিসেবে কাজ করে, তবে এটি exception হ্যান্ডলিং করে না। এটি BiConsumer ইনটারফেস গ্রহণ করে, যেখানে আপনি কাজের ফলাফল এবং exception প্রক্রিয়া করতে পারেন।
উদাহরণ: whenComplete() Exception Handling
import java.util.concurrent.CompletableFuture;
public class CompletableFutureWhenCompleteExample {
public static void main(String[] args) {
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
if (true) {
throw new RuntimeException("Error occurred!");
}
return 50;
});
// whenComplete() ব্যবহার করে exception এবং result উভয়ই প্রক্রিয়া করা
future.whenComplete((result, ex) -> {
if (ex != null) {
System.out.println("Exception: " + ex.getMessage());
} else {
System.out.println("Result: " + result);
}
}).join(); // join() ব্যবহার করে asynchronous কাজের ফলাফল পাওয়া
}
}এখানে whenComplete() মেথডটি সফলভাবে কাজ শেষ হলে ফলাফল এবং exception উভয়ই প্রসেস করে।
৬. get() এবং join() মেথড
get()মেথডটিInterruptedExceptionবাExecutionExceptionছুড়ে দেয় যদি কোনো exception ঘটে।join()মেথডটিRuntimeExceptionছুড়ে দেয় যদি কোনো exception ঘটে।
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
return 50;
});
// get() মেথড ব্যবহার
try {
System.out.println("Result using get: " + future.get());
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
// join() মেথড ব্যবহার
System.out.println("Result using join: " + future.join());সারসংক্ষেপ
CompletableFutureহল Java 8-এ আসা একটি শক্তিশালী ফিচার যা asynchronous programming এর জন্য ব্যবহৃত হয়।exceptionally(),handle(), এবংwhenComplete()মেথডের মাধ্যমে exception handling সহজ করা হয়েছে।CompletableFutureঅ্যাসিঙ্ক্রোনাস কাজের ফলস্বরূপ exception হ্যান্ডলিং, callback এবং ফলাফল প্রাপ্তির জন্য কার্যকরী উপায় প্রদান করে।
Read more