Java Threads සිංහලෙන් | Thread Class & Runnable Interface SC Guide

Java Threads සිංහලෙන් | Thread Class & Runnable Interface SC Guide

ආයුබෝවන් කොම්පියුටර් පිස්සෝ හැමෝටම! කොහොමද ඉතින්? අදත් අපි ආවා ඔයාලගේ දැනුමට තවත් පොඩි අත්වැලක් දෙන්න. විශේෂයෙන්ම Java ගැන උනන්දු අයට අද දවසේ පෝස්ට් එක ගොඩක් වැදගත් වෙයි කියලා විශ්වාසයි.

අද අපි කතා කරන්න යන්නේ Java Threads ගැන. මේක මාරම වැදගත් මාතෘකාවක්, මොකද ගොඩක් advanced applications වලදී concurrency (වැඩ කිහිපයක් එකවර කිරීම) කියන දේ අත්‍යවශ්‍යයි. හිතන්නකෝ ඔයාගේ computer එකේ එකම වෙලාවක song එකක් play වෙනවා, background එකේ software update එකක් වෙනවා, ඒ වගේම ඔයා browser එකේ වැඩත් කරනවා. මේ හැමදේම එකපාරට වෙන්නේ කොහොමද? එතනට තමයි Threads කියන concept එක එන්නේ.

සරලවම කිව්වොත්, Thread එකක් කියන්නේ program එකක් ඇතුළේ තියෙන single sequence of execution එකක්. ඒ කියන්නේ, අපේ program එකේ task එකක් එකවර කරන්න පුළුවන් පොඩි කොටස් වලට කඩලා, ඒ හැම කොටසක්ම තනි තනිවම එකම වෙලාවක execute කරන්න පුළුවන් වෙන එක තමයි Threads වලින් කරන්නේ. මේකෙන් අපේ applications වල performance එක වැඩි වෙනවා වගේම user experience එකත් improve වෙනවා. අද අපි බලමු Java වල Threads හදන්නේ කොහොමද කියලා, ඒකට තියෙන ප්‍රධාන ක්‍රම දෙක ගැන විස්තරාත්මකව කතා කරමු.

Thread මොකක්ද මේ? (What is a Thread?)

අපි හිතමු ඔයාට ගෙදර වැඩ කිහිපයක් එකම වෙලාවක කරන්න තියෙනවා කියලා. උදාහරණයක් විදිහට, බත් උයන ගමන් එළවළු කපන්න ඕනේ, ඒ අතරේ පොඩි හාමුදුරුවන්ට පාඩම් කියලා දෙන්නත් ඕනේ. ඔයා මේ හැමදේම තනි පුද්ගලයෙක් විදිහට එකින් එක කළොත් වෙලාව ගොඩක් යනවා නේද? ඒත්, ඔයාගේ අම්මා, තාත්තා, නංගි, මල්ලි වගේ අයත් ඔයාට උදව් කළොත්, ඒ කියන්නේ හැමෝම එක එක වැඩ කළොත්, වැඩේ ගොඩක් ඉක්මනට ඉවර කරන්න පුළුවන්. Thread එකක් කියන්නෙත් ඒ වගේ තමයි. Program එකක් ඇතුළේ එකම වෙලාවක වැඩ කරන්න පුළුවන් පොඩි “task” එකක්. මේ පොඩි tasks එකිනෙකට ස්වාධීනව (independently) run කරන්න පුළුවන්. මේකෙන් CPU එකේ resources උපරිමයෙන් පාවිච්චි කරන්න පුළුවන් වෙනවා, මොකද එක task එකක් ඉවර වෙනකම් අනිත් task එකට බලන් ඉන්න ඕනේ නැති නිසා.

Java වලදී, Threads implement කරන්න ප්‍රධාන ක්‍රම දෙකක් තියෙනවා:

  1. Thread class එක extend කිරීමෙන්.
  2. Runnable interface එක implement කිරීමෙන්.

අපි දැන් මේ හැම ක්‍රමයක්ම පැහැදිලිව, code examples එක්ක බලමු.

Thread Class එක පාවිච්චි කරලා Threads හදමු (Let's create Threads using Thread Class)

Thread class එක කියන්නේ Java වල Threading functionalities වලට මූලිකම පදනම. අපිට ඕන නම් අපේම custom Thread එකක් හදාගන්න, Thread class එක extend කරලා ඒකේ තියෙන run() method එක override කරන්න පුළුවන්. run() method එක ඇතුළේ තමයි Thread එකෙන් කරන්න ඕන වැඩේ (task) ලියන්නේ.

පොඩි උදාහරණයක් (A Small Example):

අපි හිතමු අපිට "Hello from Thread!" කියලා පණිවිඩයක් 5 පාරක් print කරන්න ඕන කියලා. ඒක වෙනම Thread එකකින් කරන හැටි බලමු.


// 1. Thread Class එක extend කරමු
class MyCustomThread extends Thread {
    @Override
    public void run() {
        // මේ Thread එකෙන් කරන්න ඕන වැඩේ මෙතන ලියමු
        for (int i = 0; i < 5; i++) {
            System.out.println("Hello from MyCustomThread: " + (i + 1));
            try {
                // පොඩි වෙලාවක් Thread එක නිදිකරවමු (milliseconds)
                Thread.sleep(500); // 0.5 second pause
            } catch (InterruptedException e) {
                System.out.println("MyCustomThread was interrupted.");
            }
        }
    }
}

public class ThreadClassExample {
    public static void main(String[] args) {
        // 2. අපේ custom Thread එකේ object එකක් හදමු
        MyCustomThread thread1 = new MyCustomThread();
        MyCustomThread thread2 = new MyCustomThread(); // තව Thread එකක්

        // 3. Thread එක පටන් ගන්න start() method එක call කරමු
        // වැදගත්: run() call කරනවා වෙනුවට start() call කරන්න.
        // start() එකෙන් අලුත් execution thread එකක් හදලා ඒක ඇතුළේ run() execute කරනවා.
        // run() කෙලින්ම call කළොත් Thread එකක් හැදෙන්නේ නැහැ, සාමාන්‍ය method එකක් වගේ execute වෙනවා.
        thread1.start();
        thread2.start(); // දෙවෙනි Thread එකත් පටන් ගමු

        // Main Thread එකෙන් කරන වැඩේ
        for (int i = 0; i < 5; i++) {
            System.out.println("Hello from Main Thread: " + (i + 1));
            try {
                Thread.sleep(600); // Main Thread එකත් පොඩි වෙලාවක් නිදිකරවමු
            } catch (InterruptedException e) {
                System.out.println("Main Thread was interrupted.");
            }
        }
    }
}

මේ code එක run කරලා බලන්න. output එකේ MyCustomThread එකේ messagesයි Main Thread එකේ messagesයි mix වෙලා print වෙනවා පෙනෙයි. ඒ කියන්නේ මේ Threads දෙක එකම වෙලාවක (හෝ එකිනෙකට ඉතා ආසන්නව) run වෙනවා කියන එකයි. වැදගත්ම දේ තමයි start() method එක call කරන්න අමතක කරන්න එපා. run() method එක කෙලින්ම call කළොත් ඒක සාමාන්‍ය method එකක් වගේ current thread එකේම execute වෙනවා මිසක් අලුත් Thread එකක් හදන්නේ නෑ.

Runnable Interface එකෙන් Threads හදන හැටි (How to create Threads using Runnable Interface)

Thread class එක extend කරනවාට වඩා, Java වලදී Threads හදන්න ගොඩක් වෙලාවට නිර්දේශ කරන්නේ Runnable interface එක implement කරන එක. ඒකට ප්‍රධාන හේතුවක් තියෙනවා: Java වලදී එක class එකකට extend කරන්න පුළුවන් එක class එකක් විතරයි. ඒ කියන්නේ, ඔයාගේ class එකට Thread class එක extend කළා නම්, ඒකට වෙන කිසිම class එකක් extend කරන්න බැහැ. ඒත් Runnable interface එක implement කළා නම්, ඔයාගේ class එකට වෙන class එකක් extend කරන්න පුළුවන්, මොකද interfaces ඕන තරම් implement කරන්න පුළුවන් නිසා (implements Runnable, AnotherInterface).

Runnable interface එකට තියෙන්නේ run() කියලා abstract method එකක් විතරයි. මේ method එක implement කරලා ඒක ඇතුළේ තමයි Thread එකෙන් කරන්න ඕන logic එක ලියන්නේ.

Runnable පාවිච්චි කරලා උදාහරණයක් (Example using Runnable):


// 1. Runnable Interface එක implement කරමු
class MyRunnableTask implements Runnable {
    private String taskName;

    public MyRunnableTask(String name) {
        this.taskName = name;
    }

    @Override
    public void run() {
        // මේ Thread එකෙන් කරන්න ඕන වැඩේ මෙතන ලියමු
        for (int i = 0; i < 5; i++) {
            System.out.println("Hello from " + taskName + ": " + (i + 1));
            try {
                Thread.sleep(400); // පොඩි වෙලාවක් Thread එක නිදිකරවමු
            } catch (InterruptedException e) {
                System.out.println(taskName + " was interrupted.");
            }
        }
    }
}

public class RunnableInterfaceExample {
    public static void main(String[] args) {
        // 2. Runnable object එකක් හදමු
        MyRunnableTask task1 = new MyRunnableTask("Runnable-Thread-1");
        MyRunnableTask task2 = new MyRunnableTask("Runnable-Thread-2");

        // 3. Runnable object එක Thread class එකේ constructor එකට දාලා Thread objects හදමු
        Thread thread1 = new Thread(task1);
        Thread thread2 = new Thread(task2);

        // 4. Threads පටන් ගන්න start() call කරමු
        thread1.start();
        thread2.start();

        // Main Thread එකෙන් කරන වැඩේ
        for (int i = 0; i < 5; i++) {
            System.out.println("Hello from Main Thread: " + (i + 1));
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                System.out.println("Main Thread was interrupted.");
            }
        }
    }
}

මේ උදාහරණයේදීත් කලින් වගේම Threads එකවර run වෙනවා. මෙතනදී අපි Runnable object එකක් හදලා ඒක Thread class එකේ constructor එකට දීලා තමයි Thread එකක් හදාගත්තේ. මේකෙන් අපිට MyRunnableTask class එකට වෙන class එකක් extend කරන්න වුනත් හැකියාව තියෙනවා.

Thread vs Runnable - මොකක්ද හොඳ? (Thread vs Runnable - Which is better?)

දැන් ඔයාලට ප්‍රශ්නයක් ඇති, මේ ක්‍රම දෙකෙන් මොකක්ද හොඳ කියලා. ඇත්තටම දෙකම Threads හදන්න පුළුවන්, හැබැයි පොඩි වෙනස්කම් ටිකක් තියෙනවා.

  • Single Inheritance Limitation: Thread class එක extend කළොත්, ඔයාට වෙන class එකක් extend කරන්න බැහැ. ඒත් Runnable implement කළොත්, ඔයාට වෙන class එකක් extend කරන්නත්, වෙන interfaces implement කරන්නත් පුළුවන්. මේක Java වල "composition over inheritance" කියන principle එකටත් ගොඩක් ගැළපෙනවා.
  • Resource Sharing: Runnable පාවිච්චි කරන එකෙන් එකම Runnable object එක, Threads කිහිපයකට share කරන්න පුළුවන්. ඒ කියන්නේ, එකම task logic එක Threads කිහිපයකින් run කරන්න පුළුවන්, එකම data set එකක වැඩ කරනවා වගේ. Thread class එක extend කළොත්, හැම Thread එකටම තමන්ගේම object එකක් හදන්න වෙනවා, මොකද Thread class එකම තමයි task එකත්.

Lambda Expressions: Java 8 ඉඳලා Runnable interface එක lambda expressions වලින් ලියන්න පුළුවන්. මේකෙන් code එක තවත් කෙටි වෙනවා වගේම කියවන්නත් පහසු වෙනවා. උදාහරණයක් විදිහට:


        // Runnable lambda expression එකක්
        Thread lambdaThread = new Thread(() -> {
            System.out.println("Hello from Lambda Thread!");
        });
        lambdaThread.start();
        

මේක තවත් නම්‍යශීලී (flexible) වෙනවා නේද?

ගොඩක් වෙලාවට, Java community එක නිර්දේශ කරන්නේ Runnable interface එක පාවිච්චි කරන එකයි, මොකද ඒකෙන් code එකට වැඩි නම්‍යශීලීතාවයක් (flexibility) ලැබෙනවා වගේම design එකත් හොඳ වෙනවා. Thread class එක extend කරන්නේ ගොඩක් වෙලාවට Thread එකේම behaviour එක customize කරන්න ඕන වගේ විශේෂ අවස්ථා වලදී විතරයි.

නිතර අහන ප්‍රශ්න (Frequently Asked Questions)

Q: run() method එකයි start() method එකයි අතර වෙනස මොකක්ද?

A: start() method එක call කළාම Java Virtual Machine (JVM) එක අලුත් execution thread එකක් හදලා, ඒ thread එක ඇතුළේ run() method එක execute කරනවා. මේකෙන් තමයි parallelism (සමාන්තරකරණය) ඇතිවෙන්නේ. හැබැයි run() method එක කෙලින්ම call කළොත්, ඒක සාමාන්‍ය method එකක් වගේ current thread එකේම execute වෙනවා. ඒකෙන් අලුත් Thread එකක් හැදෙන්නෙත් නෑ, parallelism එකක් වෙන්නෙත් නෑ.

Q: Threads වල synchronization කියන්නේ මොකක්ද?

A: Threads කිහිපයක් එකම shared resource එකක් (උදා: එකම variable එකක්) modify කරන්න හදනකොට, data inconsistency (දත්ත අස්ථාවරත්වය) ඇතිවෙන්න පුළුවන්. මේක වළක්වගන්න තමයි synchronization කියන concept එක පාවිච්චි කරන්නේ. Java වල synchronized keyword එක, wait(), notify(), notifyAll() methods, සහ java.util.concurrent package එකේ තියෙන Lock වගේ දේවල් මේකට පාවිච්චි කරනවා. මේක තවත් advanced topic එකක්, ඒ ගැන පස්සේ වෙනම ලිපියකින් කතා කරමු.

අවසාන වශයෙන් (Finally)

හරි ඉතින්! අද අපි Java Threads හදන ප්‍රධාන ක්‍රම දෙක ගැන ඉගෙන ගත්තා. Thread class එක extend කරන එකයි, Runnable interface එක implement කරන එකයි. මේ දෙකම Java applications වල performance එක වැඩි කරන්න වගේම responsive user interfaces හදන්නත් අත්‍යවශ්‍යයි. විශේෂයෙන්ම, Runnable interface එක පාවිච්චි කරන එකෙන් code එකට වැඩි නම්‍යශීලීතාවයක් ලැබෙන බව අපි දැක්කා.

මේ concepts ගැන තේරුම් ගන්න හොඳම විදිහ තමයි ඒවා practically කරලා බලන එක. ඒ නිසා අදම මේ examples ටික ඔයාගේ IDE එකේ (IntelliJ IDEA, Eclipse, VS Code වගේ එකක) run කරලා බලන්න. පොඩි වෙනස්කම් කරලා output එක බලන්න. එතකොට තමයි හරියටම concept එක ඔලුවට යන්නේ. මේ ගැන මොනවා හරි ප්‍රශ්න තියෙනවා නම්, පහළින් comment එකක් දාන්න. ඔයාලගේ අදහස්, ප්‍රශ්න, යෝජනා අපිට ගොඩක් වටිනවා.

තවත් අලුත් Technical knowledge එකක් අරගෙන ඔයාලව හමුවෙන්න එන්නම්. එතකම් පරිස්සමින් ඉන්න, Coding කර කර ඉන්න! ඈ...

ජය වේවා!