Threads হলো প্রোগ্রামে একাধিক কার্যক্রম (tasks) বা কাজ একসাথে সম্পাদন করার উপায়। OOP (Object-Oriented Programming) এ, এবং বিশেষ করে Java বা অন্যান্য আধুনিক ভাষায়, threads ব্যবহৃত হয় একাধিক কাজের কার্যকরী এবং সমান্তরাল (parallel) কার্যক্রম পরিচালনা করতে। তবে, একাধিক থ্রেডের মধ্যে সঠিকভাবে ডেটা পরিচালনা করার জন্য Synchronization প্রয়োজন।
Threads তৈরি করা
Thread তৈরি করার জন্য প্রধানত দুটি পদ্ধতি রয়েছে:
- Thread ক্লাস এক্সটেন্ড করে
- Runnable ইন্টারফেস ইমপ্লিমেন্ট করে
১. Thread ক্লাস এক্সটেন্ড করে Thread তৈরি করা
এই পদ্ধতিতে Thread ক্লাসকে সাবক্লাস হিসেবে এক্সটেন্ড করে থ্রেড তৈরি করা হয়। আপনি run() মেথডে থ্রেডের কার্যাবলী নির্ধারণ করবেন।
উদাহরণ:
class MyThread extends Thread {
public void run() {
System.out.println("Thread is running.");
}
}
public class ThreadExample {
public static void main(String[] args) {
MyThread t1 = new MyThread(); // Thread object তৈরি করা
t1.start(); // Thread চালু করা
}
}ব্যাখ্যা:
- এখানে
MyThreadক্লাসThreadক্লাসকে এক্সটেন্ড করেছে এবংrun()মেথডে থ্রেডের কার্যাবলী নির্ধারণ করা হয়েছে। start()মেথড থ্রেডটি চালু করে এবংrun()মেথড কার্যকর হয়।
২. Runnable ইন্টারফেস ইমপ্লিমেন্ট করে Thread তৈরি করা
এখানে Runnable ইন্টারফেস ইমপ্লিমেন্ট করা হয় এবং Thread ক্লাসের মাধ্যমে এটি ব্যবহার করা হয়।
উদাহরণ:
class MyRunnable implements Runnable {
public void run() {
System.out.println("Thread is running using Runnable.");
}
}
public class ThreadExample {
public static void main(String[] args) {
MyRunnable myRunnable = new MyRunnable(); // Runnable object তৈরি করা
Thread t1 = new Thread(myRunnable); // Thread তৈরি করা
t1.start(); // Thread চালু করা
}
}ব্যাখ্যা:
- এখানে
MyRunnableক্লাসRunnableইন্টারফেস ইমপ্লিমেন্ট করেছে, এবংrun()মেথডে থ্রেডের কার্যাবলী নির্ধারণ করা হয়েছে। Threadক্লাসের মাধ্যমেRunnableইন্টারফেসের কার্যক্রম চালানো হয়েছে।
Synchronization Techniques (সিঙ্ক্রোনাইজেশন টেকনিক্স)
যখন একাধিক থ্রেড একই ডেটা বা রিসোর্সের ওপর কাজ করে, তখন ডেটার অবস্থা পরিবর্তিত হওয়ার সম্ভাবনা থাকে (যেমন, race conditions)। এর থেকে রক্ষা পেতে synchronization প্রয়োজন। Synchronization নিশ্চিত করে যে, একসময় শুধুমাত্র একটি থ্রেডই একটি নির্দিষ্ট ব্লক বা রিসোর্সের ওপর কাজ করবে।
১. Synchronized Method
Synchronized মডিফায়ার ব্যবহার করে আপনি মেথডগুলির ওপর synchronization প্রয়োগ করতে পারেন। এর ফলে একে একে একাধিক থ্রেড সেই মেথডটি ব্যবহার করতে পারে না।
উদাহরণ:
class Counter {
private int count = 0;
public synchronized void increment() {
count++;
}
public synchronized void decrement() {
count--;
}
public int getCount() {
return count;
}
}
public class ThreadExample {
public static void main(String[] args) {
Counter counter = new Counter();
// Thread-1 increment করবে
Thread t1 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
counter.increment();
}
});
// Thread-2 decrement করবে
Thread t2 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
counter.decrement();
}
});
t1.start();
t2.start();
}
}ব্যাখ্যা:
- এখানে
increment()এবংdecrement()মেথডেsynchronizedব্যবহার করা হয়েছে, যার মানে হল, একটি থ্রেড যখন একটি মেথডে প্রবেশ করবে, তখন অন্য থ্রেড সে মেথডে প্রবেশ করতে পারবে না। - এর মাধ্যমে race conditions এড়ানো হয় এবং ডেটার একত্রিত অবস্থা সঠিক রাখা হয়।
২. Synchronized Block
Synchronized ব্লক ব্যবহার করে নির্দিষ্ট অংশে synchronization প্রয়োগ করা যেতে পারে। এতে থ্রেড কেবলমাত্র সেই কোড ব্লকের ওপর synchronization প্রয়োগ করবে, যেটা আপনার নির্দিষ্ট করা থাকে।
উদাহরণ:
class Counter {
private int count = 0;
public void increment() {
synchronized (this) {
count++;
}
}
public void decrement() {
synchronized (this) {
count--;
}
}
public int getCount() {
return count;
}
}
public class ThreadExample {
public static void main(String[] args) {
Counter counter = new Counter();
// Thread-1 increment করবে
Thread t1 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
counter.increment();
}
});
// Thread-2 decrement করবে
Thread t2 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
counter.decrement();
}
});
t1.start();
t2.start();
}
}ব্যাখ্যা:
- এখানে
synchronized (this)ব্লক ব্যবহার করা হয়েছে, যা শুধুমাত্রincrement()এবংdecrement()মেথডের ভিতরের কোড অংশে synchronization প্রয়োগ করবে। - এর মাধ্যমে আপনি প্রোগ্রামটির কর্মক্ষমতা অপ্টিমাইজ করতে পারেন, কারণ পুরো মেথডটি না সিঙ্ক্রোনাইজ করে শুধু প্রয়োজনীয় অংশটুকু সিঙ্ক্রোনাইজ করা হয়েছে।
৩. Locks (Explicit Locks)
Java এ java.util.concurrent.locks.Lock ইন্টারফেস ব্যবহার করে আরও উন্নত synchronization সম্ভব হয়, যেখানে lock() এবং unlock() মেথড ব্যবহার করা হয়।
উদাহরণ:
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
class Counter {
private int count = 0;
private final Lock lock = new ReentrantLock();
public void increment() {
lock.lock(); // Lock acquired
try {
count++;
} finally {
lock.unlock(); // Lock released
}
}
public void decrement() {
lock.lock(); // Lock acquired
try {
count--;
} finally {
lock.unlock(); // Lock released
}
}
public int getCount() {
return count;
}
}
public class ThreadExample {
public static void main(String[] args) {
Counter counter = new Counter();
// Thread-1 increment করবে
Thread t1 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
counter.increment();
}
});
// Thread-2 decrement করবে
Thread t2 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
counter.decrement();
}
});
t1.start();
t2.start();
}
}ব্যাখ্যা:
- এখানে
ReentrantLockব্যবহার করা হয়েছে।lock.lock()মেথড দ্বারা লক নেওয়া হচ্ছে এবং কাজ শেষ হলেlock.unlock()মেথড দ্বারা লক মুক্ত করা হচ্ছে। এটি একটি নিরাপদ এবং কার্যকরী পদ্ধতি যেখানে আপনি ডেডলক সমস্যা এড়িয়ে কাজ করতে পারেন।
সারাংশ:
- Thread তৈরি: Java-তে
Threadক্লাস এক্সটেন্ড করে অথবাRunnableইন্টারফেস ইমপ্লিমেন্ট করে থ্রেড তৈরি করা যায়। - Synchronization: একাধিক থ্রেডের মধ্যে ডেটা সংঘর্ষ (race condition) থেকে রক্ষা পেতে synchronization techniques যেমন
synchronizedমেথড, ব্লক এবং লক ব্যবহার করা হয়।
Read more