জাভায় থ্রেড তৈরি ও শুরু করা

জাভা আপনাকে "নিজস্ব থ্রেডে চলার মতো কাজ" বর্ণনা করার জন্য কয়েকটি ভিন্ন পদ্ধতি দেয়। অভিজ্ঞ ডেভেলপারদের শুধু প্রতিটি পদ্ধতির সিনট্যাক্সই জানা উচিত নয়, বরং কোনটি সাধারণত কেন পছন্দ করা হয় তাও বোঝা দরকার।

Thread ক্লাস এক্সটেন্ড করা

আপনি Thread-এর সাবক্লাস তৈরি করে run() মেথড ওভাররাইড করতে পারেন:

class ReportGenerator extends Thread {
    @Override
    public void run() {
        System.out.println("Generating report on " + getName());
    }
}

public class ExtendThreadExample {
    public static void main(String[] args) {
        ReportGenerator generator = new ReportGenerator();
        generator.start();
    }
}

এই কোড একটি ReportGenerator ক্লাস তৈরি করে যা Thread-কে এক্সটেন্ড করে। run()-এর ভেতরে থ্রেডের নাম সহ একটি মেসেজ প্রিন্ট করা হয়। main মেথডে এর একটি ইন্সট্যান্স তৈরি করে start() কল করা হয়, যা একটি নতুন থ্রেডে run() চালায়।
তবে এই পদ্ধতি কাজ করলেও, জাভার একক ইনহেরিটেন্স স্লট এমন কিছুতে নষ্ট করে যা আপনার ক্লাসের মূল কাজের সাথে সম্পর্কিত নয়। এটি আপনার লজিককে Thread টাইপের সাথে শক্তভাবে জুড়ে দেয়। আধুনিক কোডে এটি খুব কমই সঠিক ডিফল্ট পছন্দ।

Runnable ইমপ্লিমেন্ট করা

আরও ভালো বিচ্ছিন্নতা আনে Runnable ইন্টারফেস ইমপ্লিমেন্ট করে সেটি একটি Thread-এ দিয়ে দেওয়া:

class ReportTask implements Runnable {
    @Override
    public void run() {
        System.out.println("Generating report on " + Thread.currentThread().getName());
    }
}

public class RunnableExample {
    public static void main(String[] args) {
        Thread t = new Thread(new ReportTask(), "report-thread");
        t.start();

        // Runnable একটি ফাংশনাল ইন্টারফেস হওয়ায় ল্যাম্বডাও কাজ করে:
        Thread t2 = new Thread(() -> System.out.println("Inline task running"));
        t2.start();
    }
}

এখানে ReportTask কেবল Runnable ইমপ্লিমেন্ট করে এবং run()-এর মধ্যে কাজ করে। main-এ একটি Thread তৈরি করে তাকে একটি নাম ও টাস্ক দেওয়া হয়, তারপর start() কল করা হয়। দ্বিতীয় উদাহরণে ল্যাম্বডা দিয়ে সংক্ষেপে একই কাজ দেখানো হয়েছে।
Runnable কাজটিকে বর্ণনা করে; Thread সেটি কীভাবে চলবে তা নির্ধারণ করে। এদের আলাদা রাখার অর্থ হলো একই Runnable পরে কোনো থ্রেড পুলে দেওয়া যাবে, একটি কাঁচা Thread-এর বদলে, ব্যবসায়িক লজিকের একটি লাইনও বদলানো ছাড়াই — এই সিরিজের পরবর্তী পর্ব সরাসরি এর ওপর ভিত্তি করে তৈরি।

Callable — যখন কাজ কোনো মান ফেরত দেয় বা এক্সেপশন ছোঁড়ে

Runnable.run() কিছু ফেরত দেয় না এবং চেকড এক্সেপশন ছুঁড়তে পারে না। যখন কোনো টাস্কের ফলাফল প্রয়োজন হয় বা সেটি চেকড এক্সেপশনে ব্যর্থ হতে পারে, তখন Callable বেশি উপযুক্ত, যদিও এটি চালাতে Thread-এর বদলে ExecutorService দরকার হয়:

import java.util.concurrent.*;

public class CallableExample {
    public static void main(String[] args) throws Exception {
        Callable<Integer> task = () -> {
            Thread.sleep(100);
            return 42;
        };

        ExecutorService executor = Executors.newSingleThreadExecutor();
        Future<Integer> future = executor.submit(task);
        System.out.println("Result: " + future.get());
        executor.shutdown();
    }
}

এই উদাহরণে একটি Callable<Integer> ল্যাম্বডা ১০০ মিলিসেকেন্ড ঘুমিয়ে ৪২ রিটার্ন করে। ExecutorService-এর মাধ্যমে টাস্কটি সাবমিট করা হয় এবং Future অবজেক্ট থেকে ফলাফল নেওয়া হয়। সবশেষে এক্সিকিউটর শাটডাউন করা জরুরি।
Callable ব্যবহার করলে আপনি সহজেই অ্যাসিনক্রোনাস কাজ থেকে মান ফেরত পেতে পারেন এবং এক্সেপশন হ্যান্ডলিংও সুবিধাজনক হয়।

যে ভুলটি প্রায় সবাই একবার করে: run() বনাম start()

সরাসরি run() কল করলে কোনো থ্রেড তৈরি হয় না — এটি কেবল আপনার বর্তমান থ্রেডেই একটি সাধারণ মেথড কল করে:

public class RunVsStart {
    public static void main(String[] args) {
        Thread t = new Thread(() -> 
            System.out.println("Executing on: " + Thread.currentThread().getName())
        );

        t.run();   // prints "main" - no new thread was created
        t.start(); // prints something like "Thread-0" - this is the real thing
    }
}

এখানে প্রথমে t.run() কল করলে ল্যাম্বডাটি main থ্রেডেই চলে এবং "main" প্রিন্ট করে। পরে t.start() কল করলে সত্যিকারের একটি নতুন থ্রেড তৈরি হয়ে তাতে run() চলে, ফলে থ্রেডের নাম আলাদা দেখায়।
start() জেভিএমকে বলে একটি নতুন ওএস থ্রেড তৈরি করে তার মধ্যে run() চালাতে; নিজে run() কল করলে তা কেবল কলিং থ্রেডেই সিঙ্ক্রোনাসভাবে কোডটি চালায়।

Share