জাভা কনকারেন্সি ফ্রেমওয়ার্ক বিভিন্ন থ্রেড ম্যানেজমেন্ট এবং কন্ট্রোল কৌশল প্রদান করে যা সমান্তরাল প্রোগ্রামিং (Parallel Programming) কে আরও কার্যকর এবং নিরাপদ করে তোলে। এখানে জাভা কনকারেন্সির প্রধান ধারণাগুলো এবং প্রয়োজনীয় কোড উদাহরণ দেওয়া হলো:
১. থ্রেড তৈরির পদ্ধতি (Thread Creation)
১.১ Thread ক্লাস ব্যবহার করে থ্রেড তৈরি
class MyThread extends Thread {
public void run() {
System.out.println("Thread is running...");
}
}
public class ThreadExample {
public static void main(String[] args) {
MyThread thread = new MyThread();
thread.start();
}
}
১.২ Runnable ইন্টারফেস ব্যবহার করে থ্রেড তৈরি
class MyRunnable implements Runnable {
public void run() {
System.out.println("Runnable thread is running...");
}
}
public class RunnableExample {
public static void main(String[] args) {
Thread thread = new Thread(new MyRunnable());
thread.start();
}
}
২. থ্রেড ম্যানেজমেন্ট
২.১ থ্রেড ঘুমানো (Thread Sleep)
public class ThreadSleepExample {
public static void main(String[] args) {
Thread thread = new Thread(() -> {
try {
System.out.println("Thread is sleeping...");
Thread.sleep(2000); // ২ সেকেন্ডের জন্য ঘুমাবে
System.out.println("Thread woke up.");
} catch (InterruptedException e) {
System.out.println("Thread interrupted.");
}
});
thread.start();
}
}
২.২ থ্রেড জয়েন (Thread Join)
public class ThreadJoinExample {
public static void main(String[] args) {
Thread thread = new Thread(() -> {
System.out.println("Thread is running...");
});
thread.start();
try {
thread.join(); // প্রধান থ্রেড অপেক্ষা করবে যতক্ষণ না এই থ্রেড শেষ হয়
System.out.println("Main thread continues after thread execution.");
} catch (InterruptedException e) {
System.out.println("Thread interrupted.");
}
}
}
৩. থ্রেড সিঙ্ক্রোনাইজেশন (Thread Synchronization)
৩.১ সিঙ্ক্রোনাইজড ব্লক
class SharedResource {
public void display(String message) {
synchronized (this) {
for (int i = 0; i < 3; i++) {
System.out.println(message + " - " + i);
}
}
}
}
public class SynchronizedBlockExample {
public static void main(String[] args) {
SharedResource resource = new SharedResource();
Thread t1 = new Thread(() -> resource.display("Thread 1"));
Thread t2 = new Thread(() -> resource.display("Thread 2"));
t1.start();
t2.start();
}
}
৩.২ সিঙ্ক্রোনাইজড মেথড
class Counter {
private int count = 0;
public synchronized void increment() {
count++;
}
public int getCount() {
return count;
}
}
public class SynchronizedMethodExample {
public static void main(String[] args) throws InterruptedException {
Counter counter = new Counter();
Thread t1 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
counter.increment();
}
});
Thread t2 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
counter.increment();
}
});
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println("Final Count: " + counter.getCount());
}
}
৪. কনকারেন্ট কালেকশন (Concurrent Collections)
৪.১ ConcurrentHashMap
import java.util.concurrent.ConcurrentHashMap;
public class ConcurrentHashMapExample {
public static void main(String[] args) {
ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();
map.put("A", 1);
map.put("B", 2);
Thread t1 = new Thread(() -> map.put("C", 3));
Thread t2 = new Thread(() -> System.out.println(map.get("B")));
t1.start();
t2.start();
}
}
৫. থ্রেড পুল ম্যানেজমেন্ট (Thread Pool Management)
৫.১ ExecutorService ব্যবহার
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadPoolExample {
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(3);
Runnable task = () -> {
System.out.println(Thread.currentThread().getName() + " is executing a task.");
};
for (int i = 0; i < 5; i++) {
executor.submit(task);
}
executor.shutdown();
}
}
৬. থ্রেড কন্ট্রোল মেকানিজম
৬.১ ReentrantLock ব্যবহার
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
class SharedResource {
private Lock lock = new ReentrantLock();
public void safeMethod() {
lock.lock();
try {
System.out.println(Thread.currentThread().getName() + " is accessing the resource.");
} finally {
lock.unlock();
}
}
}
public class ReentrantLockExample {
public static void main(String[] args) {
SharedResource resource = new SharedResource();
Thread t1 = new Thread(resource::safeMethod);
Thread t2 = new Thread(resource::safeMethod);
t1.start();
t2.start();
}
}
৬.২ Semaphore ব্যবহার
import java.util.concurrent.Semaphore;
public class SemaphoreExample {
public static void main(String[] args) {
Semaphore semaphore = new Semaphore(2);
Runnable task = () -> {
try {
semaphore.acquire();
System.out.println(Thread.currentThread().getName() + " acquired a permit.");
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
System.out.println(Thread.currentThread().getName() + " releasing a permit.");
semaphore.release();
}
};
for (int i = 0; i < 5; i++) {
new Thread(task).start();
}
}
}
কৌশল এবং টিপস
ExecutorServiceব্যবহার করুন: এটি ম্যানুয়াল থ্রেড ম্যানেজমেন্টের তুলনায় বেশি কার্যকর।- ডেডলক এড়িয়ে চলুন: থ্রেড সিঙ্ক্রোনাইজেশন ডিজাইন ভালোভাবে করুন।
- কনকারেন্ট কালেকশন ব্যবহার করুন: ম্যানুয়াল সিঙ্ক্রোনাইজেশনের প্রয়োজন কমায়।
- প্রপার টাইমআউট সেট করুন: থ্রেড বা রিসোর্স ওয়েটিং এড়ানোর জন্য।
এই উদাহরণ এবং টিপস ব্যবহার করে জাভায় থ্রেড ম্যানেজমেন্ট এবং কন্ট্রোল কার্যকরভাবে করা সম্ভব।
জাভার কনকারেন্সি মাল্টিথ্রেডিং পরিচালনা করার জন্য একটি শক্তিশালী ফিচার। নিচে Thread.start(), Thread.sleep(), এবং Thread.join() এর ভূমিকা ও ব্যবহার বিস্তারিতভাবে ব্যাখ্যা করা হলো:
১. Thread.start()
- কাজ: নতুন একটি থ্রেড শুরু করে এবং থ্রেডের
run()মেথড এক্সিকিউট করে। - ব্যাখ্যা: এটি সরাসরি
run()কল না করে একটি নতুন থ্রেড তৈরি করে। ফলে কোড মূল থ্রেড থেকে আলাদাভাবে চলে।
উদাহরণ:
class MyThread extends Thread {
@Override
public void run() {
System.out.println("Thread is running: " + Thread.currentThread().getName());
}
}
public class ThreadStartExample {
public static void main(String[] args) {
MyThread thread1 = new MyThread();
thread1.start(); // নতুন থ্রেড শুরু করবে
}
}
২. Thread.sleep()
- কাজ: থ্রেডকে নির্দিষ্ট সময়ের জন্য সাময়িকভাবে থামিয়ে দেয়।
- ব্যাখ্যা: এটি থ্রেডের এক্সিকিউশনকে নির্দিষ্ট মিলিসেকেন্ডের জন্য থামায়, তবে
InterruptedExceptionথ্রো করে যদি অন্য থ্রেড এটি বাধাগ্রস্ত করে।
উদাহরণ:
public class ThreadSleepExample {
public static void main(String[] args) {
Thread thread = new Thread(() -> {
try {
System.out.println("Thread is running...");
Thread.sleep(2000); // ২ সেকেন্ড থ্রেড থামানো
System.out.println("Thread resumed after sleep.");
} catch (InterruptedException e) {
System.out.println("Thread was interrupted.");
}
});
thread.start();
}
}
৩. Thread.join()
- কাজ: একটি থ্রেড শেষ না হওয়া পর্যন্ত অন্য থ্রেডকে অপেক্ষা করায়।
- ব্যাখ্যা: এটি মূলত একাধিক থ্রেডের ক্রমিক এক্সিকিউশন নিশ্চিত করতে ব্যবহৃত হয়।
উদাহরণ:
public class ThreadJoinExample {
public static void main(String[] args) {
Thread thread1 = new Thread(() -> {
try {
System.out.println("Thread 1 is running...");
Thread.sleep(3000); // ৩ সেকেন্ড থামানো
System.out.println("Thread 1 finished.");
} catch (InterruptedException e) {
System.out.println("Thread 1 interrupted.");
}
});
Thread thread2 = new Thread(() -> {
System.out.println("Thread 2 is running...");
});
thread1.start();
thread2.start();
try {
thread1.join(); // Thread 1 শেষ না হওয়া পর্যন্ত অপেক্ষা
System.out.println("Thread 1 completed. Now executing main thread.");
} catch (InterruptedException e) {
System.out.println("Main thread interrupted.");
}
}
}
বিস্তারিত উদাহরণ: সবকিছু একত্রে
class Task extends Thread {
private String taskName;
public Task(String taskName) {
this.taskName = taskName;
}
@Override
public void run() {
try {
System.out.println(taskName + " is running...");
Thread.sleep(2000); // ২ সেকেন্ড থ্রেড থামানো
System.out.println(taskName + " completed.");
} catch (InterruptedException e) {
System.out.println(taskName + " was interrupted.");
}
}
}
public class ConcurrencyExample {
public static void main(String[] args) {
Task task1 = new Task("Task 1");
Task task2 = new Task("Task 2");
task1.start(); // Task 1 শুরু
task2.start(); // Task 2 শুরু
try {
task1.join(); // Task 1 শেষ না হওয়া পর্যন্ত অপেক্ষা
task2.join(); // Task 2 শেষ না হওয়া পর্যন্ত অপেক্ষা
} catch (InterruptedException e) {
System.out.println("Main thread interrupted.");
}
System.out.println("All tasks completed. Main thread finished.");
}
}
Thread.start(): নতুন থ্রেড শুরু করে।Thread.sleep(): থ্রেডকে নির্দিষ্ট সময়ের জন্য থামায়।Thread.join(): নির্দিষ্ট থ্রেড শেষ না হওয়া পর্যন্ত অপেক্ষা করে।
এই কনসেপ্টগুলো সঠিকভাবে বুঝে ব্যবহার করলে মাল্টিথ্রেডিং অপারেশন সহজ ও কার্যকর করা যায়।
Java concurrency-তে Thread Interruptions এবং InterruptedException গুরুত্বপূর্ণ ভূমিকা পালন করে। এটি একটি থ্রেডকে আরেকটি থ্রেডের কার্যক্রম বন্ধ করার বা থামানোর সুযোগ দেয়। এটি সাধারণত থ্রেড ব্যবস্থাপনা বা দীর্ঘ-চলমান কাজকে সঠিকভাবে বন্ধ করতে ব্যবহৃত হয়।
Thread Interruptions
Interruptions হল একটি থ্রেডকে সংকেত (signal) দেওয়ার পদ্ধতি, যা নির্দেশ করে যে এটি থামানো উচিত বা একটি নির্দিষ্ট আচরণ করা উচিত। থ্রেড ইন্টারাপশন সরাসরি থ্রেড বন্ধ করে না; এটি কেবল একটি ফ্ল্যাগ সেট করে যা থ্রেডটি যাচাই করতে পারে।
মূল পদ্ধতিগুলি:
- interrupt(): একটি থ্রেডে ইন্টারাপশন সিগন্যাল পাঠায়।
- isInterrupted(): থ্রেডের ইন্টারাপশন ফ্ল্যাগ পরীক্ষা করে।
- Thread.interrupted(): থ্রেডের ইন্টারাপশন ফ্ল্যাগ পরীক্ষা করে এবং এটি রিসেট করে।
InterruptedException
যখন একটি থ্রেড ইন্টারাপ্ট হয় এবং এটি একটি ব্লকিং অপারেশনে (যেমন Thread.sleep(), wait(), বা join()) থাকে, তখন এটি একটি InterruptedException ছুঁড়ে দেয়।
InterruptedException এর প্রয়োজনীয়তা:
- থ্রেডকে সঠিকভাবে বন্ধ করার সুযোগ দেয়।
- সিস্টেমের রিসোর্সের অপচয় কমায়।
- একটি থ্রেডের দীর্ঘ ব্লকিং অপারেশন বন্ধ করে।
Thread Interruptions-এর উদাহরণ
১. সাধারণ ইন্টারাপশন উদাহরণ:
public class ThreadInterruptExample {
public static void main(String[] args) {
Thread thread = new Thread(() -> {
try {
for (int i = 1; i <= 5; i++) {
System.out.println("Running iteration: " + i);
Thread.sleep(1000); // ব্লকিং অপারেশন
}
} catch (InterruptedException e) {
System.out.println("Thread was interrupted during sleep.");
}
});
thread.start();
try {
Thread.sleep(3000); // মূল থ্রেড কিছুক্ষণ অপেক্ষা করে
} catch (InterruptedException e) {
e.printStackTrace();
}
thread.interrupt(); // থ্রেডে ইন্টারাপশন সিগন্যাল পাঠানো
System.out.println("Interrupt signal sent to the thread.");
}
}
আউটপুট:
Running iteration: 1
Running iteration: 2
Running iteration: 3
Thread was interrupted during sleep.
Interrupt signal sent to the thread.
২. ইন্টারাপশন ফ্ল্যাগ পরীক্ষা করা:
public class InterruptFlagExample {
public static void main(String[] args) {
Thread thread = new Thread(() -> {
while (!Thread.currentThread().isInterrupted()) {
System.out.println("Thread is running...");
try {
Thread.sleep(500); // ব্লকিং অপারেশন
} catch (InterruptedException e) {
System.out.println("Thread interrupted during sleep.");
Thread.currentThread().interrupt(); // ইন্টারাপশন ফ্ল্যাগ পুনরায় সেট করুন
}
}
System.out.println("Thread is stopping...");
});
thread.start();
try {
Thread.sleep(2000); // কিছুক্ষণ অপেক্ষা করুন
} catch (InterruptedException e) {
e.printStackTrace();
}
thread.interrupt(); // থ্রেডে ইন্টারাপশন সিগন্যাল পাঠান
}
}
আউটপুট:
Thread is running...
Thread is running...
Thread is running...
Thread interrupted during sleep.
Thread is stopping...
InterruptedException এবং Interruptions-এর সঠিক ব্যবহার
- লুপ বন্ধ করা: দীর্ঘ-চলমান লুপ বন্ধ করতে ইন্টারাপশন ব্যবহার করুন।
- রিসোর্স মুক্তি: ইন্টারাপশন পাওয়ার পরে রিসোর্স মুক্ত করুন।
- ইন্টারাপশন ফ্ল্যাগ পুনরায় সেট করা: InterruptedException ধরা হলে
Thread.currentThread().interrupt()ব্যবহার করে ফ্ল্যাগ পুনরায় সেট করুন।
InterruptedException হ্যান্ডলিং এর ভুল ও সঠিক পন্থা
ভুল পন্থা:
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace(); // শুধুমাত্র স্ট্যাকট্রেস প্রিন্ট করা
}
সঠিক পন্থা:
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt(); // ফ্ল্যাগ পুনরায় সেট করুন
System.out.println("Thread interrupted, exiting gracefully.");
}
Thread Interruptions-এর ব্যবহারিক ক্ষেত্র
- ব্লকিং অপারেশন বন্ধ করা:
sleep(),join(), এবংwait()। - থ্রেড বন্ধ করা: দীর্ঘ-চলমান কাজ বা অপ্রয়োজনীয় থ্রেড থামানো।
- সিস্টেম সিগন্যাল হ্যান্ডলিং: JVM থেকে থ্রেড সিগন্যাল পরিচালনা করা।
Thread Pool এবং Interruptions
যখন ExecutorService বা ThreadPoolExecutor ব্যবহার করা হয়, তখন shutdownNow() ব্যবহার করে থ্রেডে ইন্টারাপশন সিগন্যাল পাঠানো যেতে পারে।
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadPoolInterruptExample {
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(2);
Runnable task = () -> {
try {
while (!Thread.currentThread().isInterrupted()) {
System.out.println("Task is running...");
Thread.sleep(500); // ব্লকিং অপারেশন
}
} catch (InterruptedException e) {
System.out.println("Task interrupted.");
}
};
executor.submit(task);
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
executor.shutdownNow(); // থ্রেড বন্ধের জন্য ইন্টারাপশন পাঠান
System.out.println("Executor shutdown requested.");
}
}
- Interruptions থ্রেড পরিচালনার একটি গুরুত্বপূর্ণ টুল।
- InterruptedException সঠিকভাবে হ্যান্ডল করলে থ্রেডের কার্যক্রম সঠিকভাবে বন্ধ করা সম্ভব।
- থ্রেড ইন্টারাপশন ব্যবহার করার সময় সঠিক কৌশল অনুসরণ করুন, যেমন ফ্ল্যাগ পুনরায় সেট করা এবং রিসোর্স মুক্তি নিশ্চিত করা।
Priority Management হল জাভার মাল্টি-থ্রেডিংয়ের একটি গুরুত্বপূর্ণ অংশ। এটি থ্রেডগুলোকে প্রায়োরিটি বা অগ্রাধিকার নির্ধারণ করতে সক্ষম করে, যা নির্দেশ করে কোন থ্রেড আগে প্রসেসর সময় পাবে। জাভায় থ্রেড প্রায়োরিটি ব্যবস্থাপনা Thread.setPriority() মেথডের মাধ্যমে করা হয়।
থ্রেড প্রায়োরিটি (Thread Priority)
- প্রতিটি থ্রেডের একটি প্রায়োরিটি লেভেল থাকে, যা ১ থেকে ১০ এর মধ্যে নির্ধারিত।
- Default Priority:
Thread.NORM_PRIORITY(মানে, ৫)। - থ্রেড প্রায়োরিটি তিনটি কনস্ট্যান্টের মাধ্যমে পরিচালিত হয়:
Thread.MIN_PRIORITY= 1 (সর্বনিম্ন প্রায়োরিটি)Thread.NORM_PRIORITY= 5 (ডিফল্ট প্রায়োরিটি)Thread.MAX_PRIORITY= 10 (সর্বোচ্চ প্রায়োরিটি)
Thread.setPriority() মেথডের ব্যবহার
Thread.setPriority() মেথড ব্যবহার করে থ্রেডের প্রায়োরিটি নির্ধারণ করা হয়।
সিনট্যাক্স:
public final void setPriority(int newPriority)
newPriority: থ্রেডের নতুন প্রায়োরিটি, যা ১ থেকে ১০ এর মধ্যে হতে হবে। এর বাইরে কোনো মান দিলেIllegalArgumentExceptionছুড়ে দেয়।
কোড উদাহরণ
১. থ্রেড প্রায়োরিটির উদাহরণ
public class ThreadPriorityExample {
public static void main(String[] args) {
Thread thread1 = new Thread(() -> {
for (int i = 0; i < 5; i++) {
System.out.println("Thread 1 is running");
}
});
Thread thread2 = new Thread(() -> {
for (int i = 0; i < 5; i++) {
System.out.println("Thread 2 is running");
}
});
// প্রায়োরিটি সেট করা
thread1.setPriority(Thread.MAX_PRIORITY); // সর্বোচ্চ প্রায়োরিটি (10)
thread2.setPriority(Thread.MIN_PRIORITY); // সর্বনিম্ন প্রায়োরিটি (1)
// থ্রেড শুরু করা
thread1.start();
thread2.start();
}
}
আউটপুট (সম্ভাব্য):
Thread 1 is running
Thread 1 is running
Thread 1 is running
Thread 1 is running
Thread 1 is running
Thread 2 is running
Thread 2 is running
Thread 2 is running
Thread 2 is running
Thread 2 is running
ব্যাখ্যা: উচ্চ প্রায়োরিটি থাকা থ্রেড (Thread 1) সাধারণত বেশি প্রসেসর সময় পায়। তবে এটি JVM এর থ্রেড শিডিউলার এবং প্ল্যাটফর্মের উপর নির্ভরশীল।
২. প্রায়োরিটির সাথে একাধিক থ্রেড
public class MultiThreadPriorityExample {
public static void main(String[] args) {
Runnable task = () -> {
String threadName = Thread.currentThread().getName();
int priority = Thread.currentThread().getPriority();
for (int i = 0; i < 3; i++) {
System.out.println(threadName + " with priority " + priority + " is running");
}
};
Thread thread1 = new Thread(task, "Thread-1");
Thread thread2 = new Thread(task, "Thread-2");
Thread thread3 = new Thread(task, "Thread-3");
// প্রায়োরিটি সেট করা
thread1.setPriority(Thread.MIN_PRIORITY); // ১
thread2.setPriority(Thread.NORM_PRIORITY); // ৫ (ডিফল্ট)
thread3.setPriority(Thread.MAX_PRIORITY); // ১০
thread1.start();
thread2.start();
thread3.start();
}
}
আউটপুট (সম্ভাব্য):
Thread-3 with priority 10 is running
Thread-3 with priority 10 is running
Thread-3 with priority 10 is running
Thread-2 with priority 5 is running
Thread-2 with priority 5 is running
Thread-2 with priority 5 is running
Thread-1 with priority 1 is running
Thread-1 with priority 1 is running
Thread-1 with priority 1 is running
ব্যাখ্যা: উচ্চ প্রায়োরিটি থ্রেড (Thread-3) বেশি প্রায়োরিটি পাওয়ায়, এটি আগে এক্সিকিউট হয়। তবে কিছু ক্ষেত্রে এটি নিশ্চিত নয়, কারণ এটি প্ল্যাটফর্ম-নির্ভর।
Priority Management এর চ্যালেঞ্জ
- JVM-নির্ভরতা: থ্রেড প্রায়োরিটি সম্পূর্ণভাবে JVM-এর থ্রেড শিডিউলার এবং অপারেটিং সিস্টেমের উপর নির্ভরশীল।
- অনিশ্চিত পারফরম্যান্স: উচ্চ প্রায়োরিটি থাকা থ্রেড সর্বদা আগে চলবে এমনটি নিশ্চিত নয়।
- ডেডলক: থ্রেডের ভুল প্রায়োরিটি ম্যানেজমেন্ট ডেডলকের সম্ভাবনা বাড়ায়।
Priority Management এর সেরা পদ্ধতি
- ডিফল্ট প্রায়োরিটি ব্যবহার করুন:
Thread.NORM_PRIORITYব্যবহার করা সাধারণত নিরাপদ। - পরিকল্পিত প্রায়োরিটি নির্ধারণ করুন: শুধুমাত্র প্রয়োজন অনুযায়ী প্রায়োরিটি পরিবর্তন করুন।
- Thread Pool ব্যবহার করুন:
ExecutorsAPI এর মাধ্যমে থ্রেড পরিচালনা করতে পারলে প্রায়োরিটি সমস্যা অনেকাংশে এড়ানো যায়।
Thread.setPriority() এর মাধ্যমে জাভায় থ্রেড প্রায়োরিটি সেট করা সম্ভব। এটি থ্রেডগুলোর শিডিউলিং প্রভাবিত করতে পারে, তবে এটি সম্পূর্ণরূপে প্ল্যাটফর্ম এবং JVM এর উপর নির্ভর করে। Priority Management সঠিকভাবে প্রয়োগ করলে মাল্টি-থ্রেডিং কর্মক্ষমতা উন্নত করা সম্ভব।
Thread Yielding কী?
Thread Yielding হলো জাভার কনকারেন্সি মডেলে একটি প্রক্রিয়া, যেখানে একটি চলমান থ্রেড (Executing Thread) ইচ্ছাকৃতভাবে সিপিইউ থেকে সরে দাঁড়ায় (pause করে) এবং একই প্রায়োরিটি (priority) সম্পন্ন অন্য থ্রেডগুলোকে সিপিইউ সময় (CPU time) পেতে সাহায্য করে।
Thread.yield() কী?
Thread.yield() হলো একটি স্ট্যাটিক মেথড যা জাভার থ্রেড ক্লাসে পাওয়া যায়। এটি একটি টুল যা থ্রেডকে স্বেচ্ছায় তার এক্সিকিউশন থামিয়ে শিডিউলারকে বলে যে এটি তার কাজ সম্পূর্ণ করার জন্য অন্য থ্রেডকে সুযোগ দিতে চায়।
মূল পয়েন্ট:
Thread.yield()কোনো থ্রেডকে সম্পূর্ণভাবে থামায় না, এটি কেবলমাত্র সিপিইউ শিডিউলারকে জানায় যে থ্রেডটি সাময়িকভাবে সরে যেতে চায়।- এটি মূলত শিডিউলার-নির্ভর। কোনো নিশ্চয়তা নেই যে অন্য থ্রেডটি সুযোগ পাবে।
- এটি থ্রেডের প্রায়োরিটি এবং অপারেটিং সিস্টেমের থ্রেড শিডিউলিং অ্যালগরিদমের উপর নির্ভর করে।
Thread.yield() কেন ব্যবহার করা হয়?
- থ্রেড কনটেক্সট সুইচিং সহজ করা:
একাধিক থ্রেডকে সিপিইউ ব্যবহার করার জন্য সুযোগ প্রদান করে। - লোড শেয়ারিং (Load Sharing):
দীর্ঘমেয়াদী চলমান কাজের সময় অন্য থ্রেডগুলোর জন্য সময় বরাদ্দ করার জন্য। - ডেডলক এড়ানো:
একাধিক থ্রেডের মধ্যে ব্লক হওয়া বা স্থবিরতা (stuck) এড়ানোর জন্য। - প্রোডাক্টিভ ইফিশিয়েন্সি বাড়ানো:
লম্বা রানিং থ্রেডের সময় সিপিইউ এর কার্যক্ষমতা সঠিকভাবে শেয়ার করার জন্য।
Thread.yield() উদাহরণ
১. সাধারণ উদাহরণ:
class YieldExample implements Runnable {
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + " is running. Count: " + i);
// Yield CPU time to other threads
Thread.yield();
}
}
}
public class ThreadYieldDemo {
public static void main(String[] args) {
Thread thread1 = new Thread(new YieldExample(), "Thread-1");
Thread thread2 = new Thread(new YieldExample(), "Thread-2");
thread1.start();
thread2.start();
}
}
আউটপুট (সম্ভাব্য):
Thread-1 is running. Count: 0
Thread-2 is running. Count: 0
Thread-1 is running. Count: 1
Thread-2 is running. Count: 1
...
বিঃদ্রঃ: আউটপুট নির্ভর করে থ্রেড শিডিউলিং-এর উপর, তাই ফলাফল ভিন্ন হতে পারে।
২. প্রায়োরিটি সহ Thread.yield()
class PriorityYieldExample implements Runnable {
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + " is running with priority: " +
Thread.currentThread().getPriority() + ". Count: " + i);
Thread.yield();
}
}
}
public class ThreadPriorityYieldDemo {
public static void main(String[] args) {
Thread thread1 = new Thread(new PriorityYieldExample(), "Thread-1");
Thread thread2 = new Thread(new PriorityYieldExample(), "Thread-2");
// সেট প্রায়োরিটি
thread1.setPriority(Thread.MIN_PRIORITY); // সর্বনিম্ন প্রায়োরিটি
thread2.setPriority(Thread.MAX_PRIORITY); // সর্বোচ্চ প্রায়োরিটি
thread1.start();
thread2.start();
}
}
আউটপুট (সম্ভাব্য):
Thread-2 is running with priority: 10. Count: 0
Thread-2 is running with priority: 10. Count: 1
Thread-1 is running with priority: 1. Count: 0
...
Thread.yield() এর সীমাবদ্ধতা
- শিডিউলার-নির্ভর:
Thread.yield()নিশ্চিত করে না যে অন্য থ্রেড আসলে সুযোগ পাবে। - উন্নত প্ল্যাটফর্মে সীমিত কার্যকারিতা:
কিছু JVM বা অপারেটিং সিস্টেমে এটি কার্যকরভাবে কাজ নাও করতে পারে। - উন্নত থ্রেডিং টুলস উপলব্ধ:
উন্নত টুলস যেমনExecutorServiceএবংForkJoinPoolব্যবহারেThread.yield()এর প্রয়োজনীয়তা অনেক সময় কমে যায়।
যখন Thread.yield() ব্যবহার করবেন:
- থ্রেডিং লজিকে সাময়িক বিরতি দরকার হলে।
- অন্যান্য থ্রেডের জন্য সিপিইউ সময় ভাগ করার জন্য।
- ডেডলক বা রেস কন্ডিশন এড়ানোর জন্য।
Thread.yield() একটি সহায়ক মেথড, তবে এটি ব্যবহার করার সময় প্ল্যাটফর্ম-নির্ভর আচরণের কারণে যথাযথ বিবেচনা প্রয়োজন। আধুনিক কনকারেন্সি টুলস (যেমন Executor Framework) এর বিকল্প হিসেবে এটি অনেক ক্ষেত্রে কম কার্যকর। তবুও, যখন থ্রেডিং ব্যবস্থাপনার প্রাথমিক নিয়ন্ত্রণ দরকার হয়, তখন এটি কার্যকর একটি হাতিয়ার।
Read more