Concurrency এবং Java.util.concurrent Package গাইড ও নোট

Java Technologies - জাভা ইউটিল.প্যাকেজ (Java.util Package)
284

Concurrency এবং parallelism হল দুটি গুরুত্বপূর্ণ ধারণা যা মাল্টি-থ্রেডেড প্রোগ্রামিংয়ে ব্যবহৃত হয়। java.util.concurrent প্যাকেজটি Java-তে concurrent programming সমর্থন করার জন্য বিভিন্ন ক্লাস এবং ইন্টারফেস সরবরাহ করে। এটি thread synchronization, thread safety, এবং high-performance parallel computing সম্পর্কিত সমস্যা সমাধান করতে সহায়তা করে।

Concurrency এবং Parallelism:

  1. Concurrency: এটি একাধিক কাজ (threads) একই সময়ের মধ্যে শুরু এবং সম্পন্ন হতে পারে, কিন্তু পুরোপুরি একসাথে কাজ করতে নাও পারে।
  2. Parallelism: এটি একাধিক কাজ (threads) একই সময়ে একসাথে সম্পাদিত হয়।

Java-তে java.util.concurrent প্যাকেজটি এমন কাজগুলি করতে সহায়তা করে যা concurrent বা parallel execution প্রয়োজন, যেমন thread management, task scheduling, synchronization, এবং data consistency নিশ্চিত করা।

java.util.concurrent প্যাকেজ: ক্লাস এবং ইন্টারফেস

java.util.concurrent প্যাকেজটি Java-তে multi-threading এবং concurrency সম্পর্কিত সমস্যাগুলির সমাধান করতে অনেক শক্তিশালী ক্লাস এবং ইন্টারফেস সরবরাহ করে। কিছু গুরুত্বপূর্ণ ক্লাস এবং ইন্টারফেসের মধ্যে রয়েছে:


1. Executor Framework

Executor এবং ExecutorService ইন্টারফেসগুলো thread management এবং task execution সহজ করতে ব্যবহৃত হয়। এটি থ্রেড পুল ব্যবহার করে একাধিক কাজ পরিচালনা করে।

Executor Interface:

Executor ইন্টারফেস একটি সাধারণ execute() মেথড সরবরাহ করে, যা নির্দিষ্ট একটি Runnable টাস্ককে এক্সিকিউট করতে ব্যবহার হয়।

ExecutorService Interface:

ExecutorService হল Executor ইন্টারফেসের একটি উন্নত ভার্সন, যা future এবং shutdown সম্পর্কিত আরও উন্নত ফিচার সরবরাহ করে।

Example: ExecutorService Example

import java.util.concurrent.*;

public class ExecutorServiceExample {
    public static void main(String[] args) {
        // ExecutorService ব্যবহার করে থ্রেড পুল তৈরি করা
        ExecutorService executor = Executors.newFixedThreadPool(3);

        // Runnable task তৈরি করা
        Runnable task = () -> {
            System.out.println(Thread.currentThread().getName() + " is executing task.");
        };

        // Task চালানো
        executor.submit(task);
        executor.submit(task);
        executor.submit(task);

        // Executor বন্ধ করা
        executor.shutdown();
    }
}

Output:

pool-1-thread-1 is executing task.
pool-1-thread-2 is executing task.
pool-1-thread-3 is executing task.

ব্যাখ্যা:

  • newFixedThreadPool(3) দ্বারা ৩টি থ্রেড সহ থ্রেড পুল তৈরি করা হয়েছে।
  • submit() মেথডের মাধ্যমে তিনটি টাস্ক এক্সিকিউট করা হয়েছে।
  • shutdown() মেথডের মাধ্যমে ExecutorService বন্ধ করা হয়েছে।

2. CountDownLatch

CountDownLatch হল একটি সিঙ্ক্রোনাইজেশন হেল্পার, যা এক বা একাধিক থ্রেডের অপেক্ষা করার জন্য ব্যবহৃত হয় যতক্ষণ না অন্যান্য থ্রেডগুলি তাদের কাজ সম্পন্ন করে।

Example: CountDownLatch Example

import java.util.concurrent.*;

public class CountDownLatchExample {
    public static void main(String[] args) throws InterruptedException {
        // CountDownLatch তৈরি করা, যা 3টি থ্রেডের জন্য অপেক্ষা করবে
        CountDownLatch latch = new CountDownLatch(3);

        // 3টি থ্রেড শুরু করা
        Runnable task = () -> {
            try {
                System.out.println(Thread.currentThread().getName() + " is working.");
                Thread.sleep(1000); // Some work
                latch.countDown(); // Signal that this thread has completed work
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        };

        for (int i = 0; i < 3; i++) {
            new Thread(task).start();
        }

        // Main thread waits until all worker threads complete their work
        latch.await();
        System.out.println("All tasks are completed.");
    }
}

Output:

Thread-0 is working.
Thread-1 is working.
Thread-2 is working.
All tasks are completed.

ব্যাখ্যা:

  • CountDownLatch(3) দ্বারা ৩টি থ্রেডের জন্য ল্যাচ তৈরি করা হয়েছে।
  • প্রতিটি থ্রেড countDown() কল করে ল্যাচকে ডাউনডেট করে, এবং মেইন থ্রেড await() মেথড ব্যবহার করে অপেক্ষা করে যতক্ষণ না সব থ্রেড তাদের কাজ সম্পন্ন করে।

3. Semaphore

Semaphore হলো একটি সিঙ্ক্রোনাইজেশন টুল যা নির্দিষ্ট পরিমাণ রিসোর্সে অ্যাক্সেস কন্ট্রোল করতে ব্যবহৃত হয়। এটি কনকারেন্ট থ্রেডের মধ্যে সিম্বলিক লক বা সীমিত সংখ্যক রিসোর্সের অ্যাক্সেস কন্ট্রোল করতে সহায়ক।

Example: Semaphore Example

import java.util.concurrent.*;

public class SemaphoreExample {
    public static void main(String[] args) throws InterruptedException {
        // Semaphore তৈরি করা, যার মাধ্যমে 2টি থ্রেড একসাথে কাজ করতে পারবে
        Semaphore semaphore = new Semaphore(2);

        Runnable task = () -> {
            try {
                semaphore.acquire();
                System.out.println(Thread.currentThread().getName() + " acquired a permit.");
                Thread.sleep(2000); // Simulate work
                semaphore.release();
                System.out.println(Thread.currentThread().getName() + " released a permit.");
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        };

        // 5টি থ্রেড চালানো
        for (int i = 0; i < 5; i++) {
            new Thread(task).start();
        }
    }
}

Output:

Thread-0 acquired a permit.
Thread-1 acquired a permit.
Thread-0 released a permit.
Thread-1 released a permit.
Thread-2 acquired a permit.
Thread-3 acquired a permit.
Thread-2 released a permit.
Thread-3 released a permit.
Thread-4 acquired a permit.
Thread-4 released a permit.

ব্যাখ্যা:

  • Semaphore(2) এর মাধ্যমে ২টি থ্রেড একসাথে কাজ করার অনুমতি পেয়েছে। থ্রেডরা acquire() এবং release() মেথডের মাধ্যমে সেমাফোরের লক অর্জন এবং মুক্তি পায়।

4. CopyOnWriteArrayList এবং CopyOnWriteArraySet

CopyOnWriteArrayList এবং CopyOnWriteArraySet থ্রেড-সেফ List এবং Set কোলেকশনের কার্যকরী ভার্সন। এই কোলেকশনগুলি যখন লেখা (write) হয়, তখন একটি নতুন কপি তৈরি করা হয়, তাই একাধিক থ্রেড একসাথে এই কোলেকশনগুলি পড়তে (read) পারবে কিন্তু লেখার সময় অন্য থ্রেডদের বাধা দিবে না।

Example: CopyOnWriteArrayList Example

import java.util.concurrent.CopyOnWriteArrayList;

public class CopyOnWriteArrayListExample {
    public static void main(String[] args) {
        // CopyOnWriteArrayList তৈরি করা
        CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>();
        list.add("Java");
        list.add("Python");
        list.add("JavaScript");

        // লেখার সময় একটি কপি তৈরি হবে
        list.add("C++");

        // পড়ার সময় থ্রেড-সেফ
        list.forEach(System.out::println);
    }
}

Output:

Java
Python
JavaScript
C++

java.util.concurrent প্যাকেজটি concurrent programming এবং parallel processing সম্পর্কিত অনেক সমস্যার সমাধান প্রদান করে। Executor framework, CountDownLatch, Semaphore, CopyOnWriteArrayList, CopyOnWriteArraySet এবং অন্যান্য synchronization tools এর মাধ্যমে আপনি thread management, task execution, এবং resource sharing সমস্যাগুলি সহজেই মোকাবেলা করতে পারবেন। এটি মাল্টি-থ্রেডিং প্রোগ্রাম তৈরি করার সময় কার্যকরী সমাধান প্রদান করে এবং পারফরম্যান্স অপটিমাইজেশন নিশ্চিত করে।

Content added By

Concurrency এর ধারণা এবং কেন প্রয়োজন?

284

Concurrency হল একটি প্রোগ্রামিং কনসেপ্ট যেখানে একাধিক কাজ একসাথে (একই সময়ে) সম্পাদন করা হয়। এটি বিশেষভাবে গুরুত্বপূর্ণ যখন একটি প্রোগ্রামকে দ্রুত এবং কার্যকরীভাবে কাজ করতে হয়, যেমন একাধিক ইউজারকে সার্ভিস প্রদান করতে, বড় ডেটা প্রসেস করতে, অথবা একাধিক থ্রেডে সমান্তরালভাবে কাজ করতে। Java প্রোগ্রামিং ভাষা concurrency সমর্থন করে, এবং java.util.concurrent প্যাকেজটি এই ধারণাটি বাস্তবায়ন করতে সাহায্য করে।

Concurrency এর গুরুত্ব এবং প্রয়োজনীয়তা:

  1. Performance Improvement:
    • Concurrency ব্যবহার করে একই সময়ে একাধিক কাজ সম্পাদন করা যেতে পারে, যা প্রোগ্রামের পারফরম্যান্স উন্নত করে, বিশেষ করে multi-core প্রসেসরের ব্যবহারকারী সিস্টেমে।
  2. Efficient Resource Utilization:
    • একাধিক কাজ একযোগে পরিচালনা করার মাধ্যমে CPU এর সম্পূর্ণ ক্ষমতা ব্যবহৃত হয়, যা কম্পিউটেশনাল টাস্কের প্রক্রিয়াকে দ্রুত করে তোলে।
  3. Responsiveness:
    • Concurrency প্রোগ্রামকে আরো responsive (দ্রুত প্রতিক্রিয়া জানানো) করে, কারণ যখন এক থ্রেড কোনো কাজ করছে, তখন অন্য থ্রেডটি অন্য কাজ করতে পারে। এটি বিশেষভাবে GUI applications এ কার্যকরী যেখানে ইউজারের ইন্টারঅ্যাকশন খুব দ্রুত প্রতিক্রিয়া চায়।
  4. Real-time Processing:
    • Concurrency ব্যবহার করে রিয়েল-টাইম ডেটা প্রসেসিং করা যেতে পারে, যেমন একাধিক স্ট্রিমিং ডেটা সেন্টারে প্রক্রিয়া করা।

Concurrency এবং Multithreading এর মধ্যে পার্থক্য:

  • Concurrency: একাধিক কাজ একসাথে চলতে থাকে, তবে তারা একই সময়ে পুরোপুরি চলতে নাও পারে। বরং একে একে কিন্তু দ্রুত গতিতে কাজ করে। এতে থ্রেডগুলো একে অপরের সাথে কাজ ভাগ করে নেয়।
  • Multithreading: এটি concurrency এর একটি নির্দিষ্ট রূপ যেখানে একাধিক থ্রেড parallelly (একই সময়ে) কাজ করে।

Concurrency এর জন্য Java.util.concurrent Package

Java.util.concurrent প্যাকেজটি Java-তে concurrency পরিচালনার জন্য বিভিন্ন ক্লাস, ইন্টারফেস এবং ইউটিলিটি প্রদান করে। এটি Java 5 (JDK 1.5) থেকে উপলব্ধ এবং এর মাধ্যমে multithreading, thread synchronization, এবং concurrent collections পরিচালনা করা যায়।

Java.util.concurrent এর কিছু গুরুত্বপূর্ণ উপাদান:

  1. Executor Framework:

    • Executor ফ্রেমওয়ার্ক Java-তে থ্রেড পরিচালনা এবং কাজের জন্য একটি সহজ API প্রদান করে। এর মাধ্যমে থ্রেডকে ম্যানুয়ালি তৈরি করতে না গিয়ে নির্দিষ্ট কাজগুলো নির্দিষ্ট থ্রেডপুলে আসাইন করা যায়।
    • ExecutorService এবং Executor ইন্টারফেস এর মূল উপাদান।

    উদাহরণ:

    import java.util.concurrent.*;
    
    public class ExecutorExample {
        public static void main(String[] args) {
            ExecutorService executor = Executors.newFixedThreadPool(2);
            executor.submit(() -> {
                System.out.println("Task 1 is running");
            });
            executor.submit(() -> {
                System.out.println("Task 2 is running");
            });
            executor.shutdown();
        }
    }
    
  2. Callable and Future:

    • Callable একটি ইন্টারফেস যা Runnable এর মতো, তবে এটি return মান সহ কাজ করতে পারে। Future এর মাধ্যমে Callable এর কাজ শেষ হওয়া পর্যন্ত অপেক্ষা করা এবং ফলাফল সংগ্রহ করা যায়।

    উদাহরণ:

    import java.util.concurrent.*;
    
    public class CallableExample {
        public static void main(String[] args) throws InterruptedException, ExecutionException {
            ExecutorService executor = Executors.newFixedThreadPool(1);
            Callable<Integer> task = () -> {
                return 42; // Task returns 42
            };
            Future<Integer> future = executor.submit(task);
            System.out.println("Result from Callable: " + future.get()); // Output: 42
            executor.shutdown();
        }
    }
    
  3. Concurrent Collections:

    • java.util.concurrent প্যাকেজে কিছু কনকারেন্ট Collections রয়েছে যেমন CopyOnWriteArrayList, ConcurrentHashMap, BlockingQueue ইত্যাদি, যেগুলি থ্রেড সেফ এবং একাধিক থ্রেড থেকে একযোগে ডেটা অ্যাক্সেসের জন্য উপযুক্ত।
    • ConcurrentHashMap: এটি HashMap এর মতো, তবে এটি থ্রেড সেফ এবং একাধিক থ্রেডের জন্য কার্যকরী।
    • CopyOnWriteArrayList: এটি ArrayList এর একটি থ্রেড সেফ সংস্করণ যেখানে লেখা অপারেশনগুলি সম্পাদিত হওয়ার সময় অন্যান্য থ্রেডকে লক করতে হয় না।

    উদাহরণ:

    import java.util.concurrent.*;
    
    public class ConcurrentCollectionExample {
        public static void main(String[] args) {
            ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();
            map.put("John", 25);
            map.put("Alice", 30);
            map.put("Bob", 35);
    
            // Multiple threads accessing the map
            map.forEach((key, value) -> System.out.println(key + ": " + value));
        }
    }
    
  4. Locks and Synchronization:

    • Locks এবং synchronization Java-তে race conditions এবং deadlocks এড়াতে ব্যবহৃত হয়। ReentrantLock, ReadWriteLock, এবং CountDownLatch থ্রেড সিঙ্ক্রোনাইজেশনের জন্য ব্যবহৃত হতে পারে।
    • ReentrantLock: এটি একটি এক্সক্লুসিভ লক প্রদান করে যা থ্রেড-সেফ ভাবে ডেটার অ্যাক্সেস নিয়ন্ত্রণ করতে সাহায্য করে।
    • CountDownLatch: এটি থ্রেডের সমান্তরাল কাজের জন্য একটি সুক্ষ্ম উপায়, যা অন্য থ্রেডের কাজ শেষ না হওয়া পর্যন্ত অপেক্ষা করতে পারে।

    উদাহরণ: ReentrantLock

    import java.util.concurrent.locks.ReentrantLock;
    
    public class LockExample {
        private static final ReentrantLock lock = new ReentrantLock();
    
        public static void main(String[] args) {
            Runnable task = () -> {
                lock.lock();
                try {
                    System.out.println(Thread.currentThread().getName() + " is executing task");
                } finally {
                    lock.unlock();
                }
            };
    
            Thread thread1 = new Thread(task);
            Thread thread2 = new Thread(task);
            thread1.start();
            thread2.start();
        }
    }
    

Concurrency কেন প্রয়োজন?

  1. Faster Execution:
    • একাধিক কাজ একযোগে চালানোর মাধ্যমে আপনি আপনার অ্যাপ্লিকেশনের পারফরম্যান্স বৃদ্ধি করতে পারেন। বিশেষ করে multi-core processors এর ব্যবহারকারী সিস্টেমে এটি খুব কার্যকরী।
  2. Responsive Applications:
    • Concurrency ব্যবহার করে অ্যাপ্লিকেশনকে responsive করা সম্ভব, যেমন GUI applications যা ইউজারের আঙ্গুলের স্পর্শের সঙ্গে দ্রুত প্রতিক্রিয়া প্রদান করতে সক্ষম।
  3. Better Resource Utilization:
    • Concurrency সিস্টেমের সম্পূর্ণ ক্ষমতা ব্যবহৃত করে, যেমন CPU cores এবং I/O operations, যাতে কাজ দ্রুত এবং দক্ষভাবে সম্পন্ন হয়।
  4. Real-time and Parallel Processing:
    • রিয়েল-টাইম ডেটা প্রক্রিয়াকরণ এবং parallel processing কার্যক্রমে Concurrency একটি অপরিহার্য বিষয় হয়ে ওঠে।

Concurrency Java-তে কার্যকরীভাবে পরিচালনার জন্য java.util.concurrent প্যাকেজটি একটি শক্তিশালী এবং কার্যকরী উপায়। এটি উন্নত thread management, task scheduling, synchronization এবং parallel execution পরিচালনা করতে সাহায্য করে। Executor frameworks, concurrent collections, locks, এবং অন্যান্য utilities সহ Java-তে concurrency ব্যবস্থাপনা অনেক সহজ এবং কার্যকর হয়েছে, যা multi-threaded applications তৈরি করার জন্য অপরিহার্য।

Content added By

Concurrent Collections: ConcurrentHashMap, CopyOnWriteArrayList

247

Concurrency হলো একাধিক কাজ বা থ্রেড একসাথে সম্পাদন করার প্রক্রিয়া, যা প্রোগ্রামিংয়ের একটি গুরুত্বপূর্ণ অংশ। Javaconcurrent programming সমর্থন করতে java.util.concurrent প্যাকেজে কিছু বিশেষ কোলেকশন ক্লাস রয়েছে, যেগুলি একাধিক থ্রেডের মধ্যে নিরাপদভাবে ডেটা ম্যানিপুলেশন করতে সহায়তা করে। এর মধ্যে ConcurrentHashMap এবং CopyOnWriteArrayList দুটি জনপ্রিয় কোলেকশন।

এখানে আমরা ConcurrentHashMap এবং CopyOnWriteArrayList কিভাবে কাজ করে এবং কিভাবে এগুলি concurrency এর জন্য ব্যবহার করা হয় তা আলোচনা করব।


1. ConcurrentHashMap

ConcurrentHashMap হল Map ইন্টারফেসের একটি থ্রেড-সেফ বাস্তবায়ন, যা concurrent access এর জন্য ডিজাইন করা হয়েছে। এটি একাধিক থ্রেডের মধ্যে ডেটা একসাথে রিড এবং রাইট করতে সক্ষম এবং একই সময়ে একাধিক থ্রেড Map এর মানে পরিবর্তন করলেও ডেটার consistent অবস্থান বজায় রাখে। এর মানে, আপনি একাধিক থ্রেড দিয়ে একই ConcurrentHashMap অবজেক্টে কাজ করতে পারেন, কিন্তু এতে কোনো সমস্যা হবে না, কারণ এটি partitioned locks ব্যবহার করে ডেটা অ্যাক্সেস নিয়ন্ত্রণ করে।

ব্যবহার:

  • যখন আপনি একাধিক থ্রেডের মাধ্যমে একটি Map এ ডেটা রিড এবং রাইট করতে চান, তখন ConcurrentHashMap একটি নিরাপদ বিকল্প।
  • এটি একাধিক থ্রেডের মধ্যে ডেটা অ্যাক্সেসের জন্য high concurrency সরবরাহ করে এবং synchronization ম্যানেজমেন্টের জন্য নিজে থেকেই অনেক কাজ করে।

উদাহরণ:

import java.util.concurrent.ConcurrentHashMap;

public class ConcurrentHashMapExample {
    public static void main(String[] args) {
        // ConcurrentHashMap তৈরি করা
        ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();
        
        // একাধিক থ্রেড দিয়ে মান যোগ করা
        map.put("Java", 100);
        map.put("Python", 200);
        map.put("C++", 150);

        // ConcurrentHashMap থেকে মান অ্যাক্সেস করা
        System.out.println("Java score: " + map.get("Java"));
        System.out.println("Python score: " + map.get("Python"));
        System.out.println("C++ score: " + map.get("C++"));
    }
}

Output:

Java score: 100
Python score: 200
C++ score: 150

বৈশিষ্ট্য:

  • Thread-Safety: একাধিক থ্রেডের মধ্যে অ্যাক্সেস নিরাপদে পরিচালনা করতে পারে।
  • High Concurrency: একাধিক থ্রেড একযোগে ডেটা রিড এবং রাইট করতে সক্ষম।
  • No Global Locking: এটি partitioned locks ব্যবহারের মাধ্যমে প্রতিটি অংশে আলাদা লক তৈরি করে, যাতে ডেটা অ্যাক্সেস দ্রুত হয়।

2. CopyOnWriteArrayList

CopyOnWriteArrayList হলো একটি থ্রেড-সেফ List ইন্টারফেসের বাস্তবায়ন যা write operations (যেমন add(), remove()) সম্পাদন করার সময় একটি নতুন কপি তৈরি করে। এর ফলে read operations থ্রেড-সেফ হয়ে থাকে এবং কোনো রকম concurrent modification exception দেখা দেয় না।

এটি খুবই উপকারী যখন আপনার লিস্টে বেশি পড়ার (read) কাজ হচ্ছে এবং কম লেখার (write) কাজ হচ্ছে। কারণ write operations গুলি কপি তৈরি করে এবং শুধুমাত্র সেই কপি পরিবর্তন হয়, মূল কন্টেন্ট অপরিবর্তিত থাকে।

ব্যবহার:

  • এটি এমন সময় ব্যবহৃত হয় যখন আপনি অনেক বেশি reading অপারেশন করতে চান এবং কম writing অপারেশন থাকে, যেমন ক্যাশে সিস্টেমে।

উদাহরণ:

import java.util.concurrent.CopyOnWriteArrayList;

public class CopyOnWriteArrayListExample {
    public static void main(String[] args) {
        // CopyOnWriteArrayList তৈরি করা
        CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>();
        
        // লিস্টে মান যোগ করা
        list.add("Java");
        list.add("Python");
        list.add("C++");

        // লিস্টের মান প্রিন্ট করা
        for (String lang : list) {
            System.out.println(lang);
        }

        // মান মুছে ফেলা
        list.remove("Python");

        // লিস্টের মান আবার প্রিন্ট করা
        System.out.println("\nAfter removing Python:");
        for (String lang : list) {
            System.out.println(lang);
        }
    }
}

Output:

Java
Python
C++

After removing Python:
Java
C++

বৈশিষ্ট্য:

  • Thread-Safety: একাধিক থ্রেড একযোগে read করতে পারে এবং write করার সময় কপি তৈরি করে, যা থ্রেডের মাঝে কোনো রকমের সমস্যা সৃষ্টি করে না।
  • Copy on Write: যখনই একটি write operation ঘটে, তখন একটি নতুন কপি তৈরি করা হয়, ফলে read অপারেশনগুলো থ্রেড-সেফ থাকে।
  • Memory Overhead: write operations সময় অতিরিক্ত মেমরি ব্যবহৃত হতে পারে কারণ নতুন কপি তৈরি হয়।

ConcurrentHashMap এবং CopyOnWriteArrayList এর মধ্যে পার্থক্য

FeatureConcurrentHashMapCopyOnWriteArrayList
Data StructureKey-value pair (Map)List (Ordered collection)
Thread-SafetyHigh concurrency with thread-safetyThread-safety through copying on write
OperationsSupports both read and write operationsSupports read operations, write creates a new copy
Write OperationsThread-safe with partitioned locksWrite operations create a new copy of the list
Use CaseWhen high concurrency for map is neededWhen reading is frequent, and writes are rare
Memory OverheadLow (Efficient concurrency management)Higher (due to copy-on-write mechanism)

Use Cases:

  • ConcurrentHashMap:
    • Caching: যখন একাধিক থ্রেডে ডেটা রিড এবং রাইট করতে হয়, এবং ডেটার উপর অনেক কনকারেন্ট এক্সেস দরকার হয়।
    • Session Management: একাধিক থ্রেডে সেশন ডেটা রিড এবং আপডেট করার ক্ষেত্রে নিরাপত্তা এবং কর্মক্ষমতা নিশ্চিত করার জন্য।
  • CopyOnWriteArrayList:
    • Caching: যখন ডেটা বারবার পড়া হয় এবং লেখার কার্যাবলী কম থাকে, যেমন read-heavy অ্যাপ্লিকেশন।
    • Event Handling: যেখানে বেশিরভাগ সময় read (যেমন, ইভেন্ট লিস্টেনিং) করা হয় এবং ইভেন্টটি খুব কম সজ্জন করা হয়।

  • ConcurrentHashMap এবং CopyOnWriteArrayList দুটি কনকারেন্ট ডেটা স্ট্রাকচার, তবে তাদের পার্থক্য রয়েছে data access pattern এবং write operations এর ওপর।
  • ConcurrentHashMap উচ্চ কনকারেন্ট রিড এবং রাইট অপারেশনগুলির জন্য ব্যবহৃত হয় এবং এটি partitioned locks ব্যবহার করে ডেটা নিরাপদ রাখে।
  • CopyOnWriteArrayList তখন উপকারী যখন read-heavy অ্যাপ্লিকেশন থাকে, কারণ এটি write operations এর জন্য নতুন কপি তৈরি করে এবং থ্রেড-সেফভাবে ডেটা রিড করা যায়।

এই দুটি কোলেকশন থ্রেড-সেফ কনকারেন্ট প্রোগ্রামিংয়ের জন্য কার্যকরী এবং ব্যবহারকারীকে দ্রুত ডেটা ম্যানিপুলেশন করতে সহায়তা করে।

Content added By

BlockingQueue এবং LinkedBlockingQueue এর ব্যবহার

276

BlockingQueue এবং LinkedBlockingQueue ক্লাসগুলি java.util.concurrent প্যাকেজের অংশ, যা concurrent programming-এ বিশেষভাবে ব্যবহৃত হয়। এগুলি মাল্টিথ্রেডেড অ্যাপ্লিকেশনগুলিতে থ্রেডের মধ্যে সুরক্ষিত এবং সিঙ্ক্রোনাইজড ডেটা আদান-প্রদান সহজ করে তোলে। এগুলি এক্সিকিউটর এবং থ্রেড পুলে ব্যবহৃত হয়, যেখানে থ্রেডগুলির মধ্যে কাজের ভাগবাটোয়ারা এবং সিঙ্ক্রোনাইজেশন অত্যন্ত গুরুত্বপূর্ণ।

BlockingQueue এর ধারণা

BlockingQueue একটি ইন্টারফেস যা কিউ (Queue) ডেটা স্ট্রাকচার নির্ধারণ করে, এবং এতে ব্লকিং অপারেশন থাকে, যা মানে যদি কিউ ফাঁকা থাকে বা পূর্ণ থাকে, তখন কোন থ্রেড উপাদান গ্রহণ বা যোগ করতে পারবে না যতক্ষণ না সেটা সম্ভব হয়।

BlockingQueue এর প্রধান সুবিধা হলো, এটি producer-consumer problem সমাধান করতে সহায়ক, যেখানে একটি থ্রেড কাজ যোগ করে (producer) এবং অন্য থ্রেড সেই কাজ গ্রহণ করে (consumer)।

BlockingQueue এর মূল মেথডসমূহ:

  1. put(E e):
    • কিউতে একটি উপাদান যোগ করতে ব্যবহৃত হয়। যদি কিউ পূর্ণ থাকে, তাহলে এটি থ্রেডটিকে ব্লক করে যতক্ষণ না কিউতে জায়গা হয়।
  2. take():
    • কিউ থেকে একটি উপাদান গ্রহণ করতে ব্যবহৃত হয়। যদি কিউ ফাঁকা থাকে, তাহলে এটি থ্রেডটিকে ব্লক করে যতক্ষণ না কিউতে একটি উপাদান থাকে।
  3. offer(E e):
    • কিউতে একটি উপাদান যোগ করতে চেষ্টা করে, কিন্তু কিউ পূর্ণ থাকলে এটি false রিটার্ন করে এবং থ্রেড ব্লক হয় না।
  4. poll():
    • কিউ থেকে একটি উপাদান গ্রহণ করে, কিন্তু কিউ ফাঁকা থাকলে এটি null রিটার্ন করে এবং থ্রেড ব্লক হয় না।

LinkedBlockingQueue এর ধারণা

LinkedBlockingQueue হল BlockingQueue ইন্টারফেসের একটি বাস্তবায়ন, যা একটি linked list ভিত্তিক কিউ। এটি FIFO (First-In-First-Out) নিয়ম অনুসারে কাজ করে, অর্থাৎ প্রথমে যোগ করা উপাদানটি প্রথমে বের হয়ে যাবে।

LinkedBlockingQueue প্রায়ই ব্যবহৃত হয় যখন অনেক producer-consumer threads একসাথে কাজ করছে এবং যেখানে কিউ আকার ডাইনামিক হতে পারে, অর্থাৎ এটি থ্রেড-সেফ এবং ব্লকিং কিউ অপারেশন সহজে পরিচালনা করতে পারে।

LinkedBlockingQueue এর বৈশিষ্ট্য:

  1. Capacity: এটি একটি ঐচ্ছিক capacity (ধারণক্ষমতা) নির্ধারণ করতে পারে, যদি কিউ পূর্ণ থাকে তবে এটি ব্লক করবে যতক্ষণ না সেখানে জায়গা তৈরি হয়।
  2. Thread-Safety: এটি থ্রেড-সেফ। একাধিক থ্রেড নিরাপদভাবে কিউতে উপাদান যোগ করতে এবং গ্রহণ করতে পারে।
  3. Blocking Operations: ব্লকিং অপারেশনগুলির মাধ্যমে থ্রেডগুলি কিউতে উপাদান গ্রহণ বা যোগ করার জন্য সিঙ্ক্রোনাইজড থাকে।

LinkedBlockingQueue এর ব্যবহার উদাহরণ:

import java.util.concurrent.LinkedBlockingQueue;

public class LinkedBlockingQueueExample {
    public static void main(String[] args) throws InterruptedException {
        // একটি LinkedBlockingQueue তৈরি করা (capacity 10)
        LinkedBlockingQueue<Integer> queue = new LinkedBlockingQueue<>(10);

        // Producer thread
        Thread producer = new Thread(() -> {
            try {
                for (int i = 0; i < 10; i++) {
                    queue.put(i);  // কিউতে উপাদান যোগ করা
                    System.out.println("Produced: " + i);
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        });

        // Consumer thread
        Thread consumer = new Thread(() -> {
            try {
                for (int i = 0; i < 10; i++) {
                    int value = queue.take();  // কিউ থেকে উপাদান গ্রহণ
                    System.out.println("Consumed: " + value);
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        });

        producer.start();  // Producer thread শুরু করা
        consumer.start();  // Consumer thread শুরু করা

        producer.join();  // Producer thread শেষ হওয়া পর্যন্ত অপেক্ষা করা
        consumer.join();  // Consumer thread শেষ হওয়া পর্যন্ত অপেক্ষা করা
    }
}

Output:

Produced: 0
Produced: 1
Consumed: 0
Produced: 2
Consumed: 1
Produced: 3
Consumed: 2
Produced: 4
Consumed: 3
Produced: 5
Consumed: 4
Produced: 6
Consumed: 5
Produced: 7
Consumed: 6
Produced: 8
Consumed: 7
Produced: 9
Consumed: 8
Consumed: 9

ব্যাখ্যা:

  • এখানে একটি LinkedBlockingQueue তৈরি করা হয়েছে যার ধারণক্ষমতা ১০।
  • Producer thread কিউতে উপাদান যোগ করে, এবং Consumer thread কিউ থেকে উপাদান গ্রহণ করে।
  • put() মেথড producer থ্রেডকে ব্লক করে যদি কিউ পূর্ণ থাকে।
  • take() মেথড consumer থ্রেডকে ব্লক করে যদি কিউ খালি থাকে।

BlockingQueue এবং LinkedBlockingQueue এর মধ্যে পার্থক্য:

PropertyBlockingQueueLinkedBlockingQueue
Interface vs ImplementationInterfaceConcrete implementation of BlockingQueue
CapacityNo capacity limit by default (can be defined)Can define a capacity limit (default is Integer.MAX_VALUE)
Thread SafetyThread-safe, allows concurrent accessThread-safe, allows concurrent access
UsageCan be implemented by various classes (e.g., ArrayBlockingQueue)Typically used when elements are inserted and removed in FIFO order
Blocking OperationsBlock on insert or remove when full or emptyBlock on insert or remove when full or empty
  • BlockingQueue এবং LinkedBlockingQueue ক্লাসগুলি concurrent programming-এ ব্যবহৃত হয় যেখানে থ্রেডগুলির মধ্যে সিঙ্ক্রোনাইজড উপাদান আদান-প্রদান প্রয়োজন হয়।
  • LinkedBlockingQueue একটি সাধারণ বাস্তবায়ন, যা ব্লকিং অপারেশন এবং থ্রেড-সেফ ডেটা প্রক্রিয়া সরবরাহ করে। এটি FIFO নিয়মে কাজ করে এবং বড় থ্রেড-পুল ব্যবস্থার জন্য কার্যকর।
  • এই ক্লাসগুলি মাল্টিথ্রেডেড অ্যাপ্লিকেশনে যেমন producer-consumer problem সমাধানে ব্যবহৃত হয় এবং থ্রেডগুলির মধ্যে নিরাপদ ডেটা আদান-প্রদান নিশ্চিত করে।
Content added By

ExecutorService এবং Thread Pools এর মাধ্যমে Concurrency Management

241

Concurrency Management হল একটি গুরুত্বপূর্ণ ধারণা যেখানে একাধিক কাজ একসাথে (প্যারালাল) সম্পাদন করা হয়। Java-তে java.util.concurrent প্যাকেজটি concurrency এবং multi-threading এর কাজকে সহজ এবং কার্যকরী করার জন্য বিভিন্ন ক্লাস এবং ইন্টারফেস সরবরাহ করে। এর মধ্যে ExecutorService এবং Thread Pools গুলি অন্যতম শক্তিশালী টুলস যা concurrency ব্যবস্থাপনা করতে সহায়তা করে।

Concurrency এবং Thread Pools এর ধারণা

Concurrency হল একাধিক কাজের একসাথে সম্পাদন, যাতে একাধিক থ্রেড একযোগে কাজ করতে পারে এবং সময়ের ব্যবধানে সম্পন্ন হতে পারে। সাধারণত একাধিক থ্রেড তৈরি এবং তাদের মধ্যে সমন্বয় করতে Thread Pool ব্যবহৃত হয়, যা থ্রেড ব্যবস্থাপনাকে সহজ এবং কার্যকরী করে।

Thread Pool হল এমন একটি প্রোগ্রামিং ধারণা যেখানে নির্দিষ্ট সংখ্যক থ্রেড তৈরি করা হয় এবং এগুলি পুনরায় ব্যবহার করা হয় বিভিন্ন কাজ সম্পাদনের জন্য, যা থ্রেড তৈরি ও ধ্বংস করার খরচ কমিয়ে দেয় এবং সিস্টেমের কর্মক্ষমতা বাড়ায়।

ExecutorService একটি ইন্টারফেস যা Executor ইন্টারফেসের প্রসারিত সংস্করণ এবং এটি থ্রেড ব্যবস্থাপনা এবং Thread Pool এর কার্যকারিতা প্রদান করে।


ExecutorService এবং Thread Pools এর মাধ্যমে Concurrency Management

ExecutorService ইন্টারফেসটি থ্রেডের জীবনচক্র পরিচালনা করার জন্য ব্যবহৃত হয়, যেখানে Thread Pool একটি সংগ্রহ, যা নির্দিষ্ট সংখ্যক থ্রেড তৈরি করে এবং নতুন কাজের জন্য তাদের পুনঃব্যবহার করে।

ExecutorService ইন্টারফেসের প্রধান মেথডসমূহ:

  1. submit():

    • এটি একটি Runnable বা Callable কাজ গ্রহণ করে এবং একটি Future অবজেক্ট রিটার্ন করে, যা কাজটির ফলাফল বা অবস্থার ট্র্যাক রাখতে সাহায্য করে।
    ExecutorService executor = Executors.newFixedThreadPool(2);
    executor.submit(() -> {
        System.out.println("Task 1 is running");
    });
    
  2. invokeAll():
    • এটি একটি Collection এর মাধ্যমে একাধিক Callable কাজ গ্রহণ করে এবং প্রত্যেকটি কাজের ফলাফল Future অবজেক্টের মধ্যে জমা করে।
  3. shutdown():

    • থ্রেডপুলের সমস্ত থ্রেডের কাজ শেষ হলে ExecutorService বন্ধ করার জন্য ব্যবহৃত হয়। এটি নতুন কাজ গ্রহণ বন্ধ করে দেয়, তবে যে কাজগুলি ইতিমধ্যে শুরু হয়েছে সেগুলি সম্পন্ন হয়।
    executor.shutdown();
    
  4. shutdownNow():
    • এটি থ্রেডপুলের চলমান কাজগুলি শেষ করার জন্য চেষ্টা করে এবং অবিলম্বে থ্রেডগুলি বন্ধ করে দেয়।

Thread Pools এর ধারণা এবং ExecutorService এর মাধ্যমে তাদের ব্যবহার

Thread Pool ব্যবহারের মূল উদ্দেশ্য হল থ্রেড তৈরির জন্য অতিরিক্ত সময় ও সম্পদ খরচ কমানো। যখনই কোনো নতুন কাজ আসে, তখন ব্যবহৃত Thread Pool থেকে একটি থ্রেড পুনরায় ব্যবহার করা হয়।

Java-তে Executors ক্লাসের মাধ্যমে বিভিন্ন ধরনের Thread Pools তৈরি করা যায়:

  1. FixedThreadPool:

    • এটি একটি নির্দিষ্ট সংখ্যক থ্রেডের Thread Pool তৈরি করে।
    ExecutorService executor = Executors.newFixedThreadPool(3);
    
  2. CachedThreadPool:

    • এটি একটি থ্রেডপুল তৈরি করে যা প্রয়োজন অনুসারে থ্রেড তৈরি করে এবং তাদের ব্যবহারের পর পুনঃব্যবহার করে।
    ExecutorService executor = Executors.newCachedThreadPool();
    
  3. SingleThreadExecutor:

    • এটি একটি একক থ্রেডের Thread Pool তৈরি করে এবং যেকোনো সময় একটি কাজ সম্পাদন করতে ব্যবহৃত হয়।
    ExecutorService executor = Executors.newSingleThreadExecutor();
    

Practical Example: ExecutorService and Thread Pool Usage

এখানে ExecutorService এবং Thread Pool এর ব্যবহার দেখানো হয়েছে যেখানে আমরা থ্রেডপুলের মাধ্যমে একাধিক কাজ concurrently সম্পাদন করছি:

Example: Using ExecutorService for Concurrent Tasks

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ExecutorServiceExample {
    public static void main(String[] args) {
        // Fixed Thread Pool of 3 threads
        ExecutorService executorService = Executors.newFixedThreadPool(3);
        
        // Submit multiple tasks to the ExecutorService
        executorService.submit(() -> {
            System.out.println("Task 1 is running in " + Thread.currentThread().getName());
        });
        
        executorService.submit(() -> {
            System.out.println("Task 2 is running in " + Thread.currentThread().getName());
        });
        
        executorService.submit(() -> {
            System.out.println("Task 3 is running in " + Thread.currentThread().getName());
        });
        
        // Shutdown the executor service
        executorService.shutdown();
    }
}

Output:

Task 1 is running in pool-1-thread-1
Task 2 is running in pool-1-thread-2
Task 3 is running in pool-1-thread-3

ব্যাখ্যা:

  • এখানে Executors.newFixedThreadPool(3) মেথডের মাধ্যমে একটি থ্রেডপুল তৈরি করা হয়েছে যার মধ্যে ৩টি থ্রেড রয়েছে।
  • submit() মেথড ব্যবহার করে তিনটি কাজ ExecutorService এ জমা দেওয়া হয়েছে।
  • পরবর্তীতে shutdown() মেথড ব্যবহার করে থ্রেডপুলটি বন্ধ করা হয়েছে।

ExecutorService এবং Thread Pools এর মাধ্যমে Concurrency Management এর সুবিধা:

  1. Resource Management:
    • থ্রেডপুল ব্যবহারের মাধ্যমে থ্রেড তৈরি এবং ধ্বংস করার খরচ কমানো যায়, কারণ থ্রেডগুলো পুনরায় ব্যবহার করা যায়।
  2. Scalability:
    • Thread Pools থ্রেডের সংখ্যা সীমাবদ্ধ করে কাজের জন্য নির্দিষ্ট সংখ্যক থ্রেড বরাদ্দ করে, যা সিস্টেমের ওপর অতিরিক্ত চাপ সৃষ্টি হওয়া থেকে রক্ষা করে।
  3. Improved Performance:
    • ExecutorService ব্যবহারের মাধ্যমে কাজগুলির দ্রুত সমাধান হয় কারণ এটি থ্রেড ব্যবস্থাপনাকে সহজ করে এবং parallel processing এর সুযোগ প্রদান করে।
  4. Thread Safety:
    • ExecutorService ব্যবহার করলে থ্রেড ব্যবস্থাপনা সহজ হয়ে ওঠে এবং থ্রেডের মধ্যে প্রতিযোগিতা (race conditions) কমানো যায়।

ExecutorService এবং Thread Pools হল Java-তে Concurrency Management এর জন্য অত্যন্ত শক্তিশালী টুলস। এগুলি থ্রেডগুলির সঠিক ব্যবস্থাপনা করতে সহায়তা করে এবং একাধিক কাজ একসাথে সম্পাদন করার সক্ষমতা প্রদান করে। Thread Pool ব্যবহারের মাধ্যমে থ্রেড তৈরির খরচ কমানো যায় এবং সিস্টেমের কর্মক্ষমতা বাড়ানো যায়। ExecutorService ইন্টারফেসটি থ্রেডপুল পরিচালনা, থ্রেডের জীবনচক্র নিয়ন্ত্রণ এবং থ্রেডের কাজ করার জন্য সুবিধাজনক মেথড সরবরাহ করে।

Content added By
Promotion
NEW SATT AI এখন আপনাকে সাহায্য করতে পারে।

Are you sure to start over?

Loading...