Concurrent Collections এর জন্য Best Practices

Concurrent Collections - জাভা কনকারেন্সি (Java Concurrency) - Java Technologies

335

জাভার Concurrent Collections মাল্টিথ্রেডেড অ্যাপ্লিকেশনে থ্রেড-সেফ ডেটা স্ট্রাকচার সরবরাহ করে। তবে সঠিকভাবে ব্যবহার না করলে ডেডলক, ডেটা রেস বা পারফরম্যান্স সমস্যা দেখা দিতে পারে। এখানে ConcurrentHashMap, CopyOnWriteArrayList, এবং BlockingQueue সহ জাভার কনকারেন্ট কালেকশনের জন্য সেরা অনুশীলনগুলো (best practices) উল্লেখ করা হলো।


১. উপযুক্ত কনকারেন্ট কালেকশন নির্বাচন করুন

  • ConcurrentHashMap: থ্রেড-সেফ ম্যাপ যেখানে একাধিক থ্রেড থেকে ডেটা পড়া এবং লেখা করা যায়। দ্রুত read-heavy operations এর জন্য উপযুক্ত।
  • CopyOnWriteArrayList: রিড-অপ্টিমাইজড লিস্ট যেখানে লেখার সময় নতুন কপি তৈরি হয়। রিড অপারেশন বেশি হলে এটি ব্যবহার করুন।
  • BlockingQueue: প্রযোজক-গ্রাহক (Producer-Consumer) প্যাটার্নের জন্য উপযুক্ত।
  • ConcurrentSkipListMap এবং ConcurrentSkipListSet: যদি ডেটা sorted রাখতে হয়, তবে এই ক্লাস ব্যবহার করুন।

২. ডেটা রেস এড়ানোর জন্য Atomic অপারেশন ব্যবহার করুন

  • computeIfAbsent(), putIfAbsent() বা merge() ব্যবহার করুন একাধিক থ্রেডে ডেটা রেস এড়াতে।

উদাহরণ:

ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();

map.putIfAbsent("Key", 1); // ডেটা রেস এড়ানো
map.computeIfAbsent("NewKey", key -> 2); // কন্ডিশনাল ডেটা সেটিং
map.merge("Key", 1, Integer::sum); // ডেটা আপডেটের জন্য

৩. কনকারেন্ট কালেকশন থেকে রেস কন্ডিশন এড়াতে Avoid Manual Synchronization

  • কনকারেন্ট কালেকশন ব্যবহার করার সময় synchronized ব্লক প্রয়োগ করার চেষ্টা করবেন না। এটি পারফরম্যান্স কমিয়ে দিতে পারে।

Avoid (Bad Practice):

synchronized (map) {
    map.put("Key", 1);
}

Use (Good Practice):

map.put("Key", 1); // ConcurrentHashMap নিজেই থ্রেড-সেফ

৪. ইটারেটর ব্যবহার করার সময় সতর্ক থাকুন

  • ConcurrentHashMap এর ইটারেটর ডেটা পরিবর্তনের সময় fail-safe কিন্তু তাৎক্ষণিক প্রতিফলন দেয় না।
  • CopyOnWriteArrayList ইটারেটর ব্যবহার করলে এক সময়ে শুধু রিড অপারেশন নিশ্চিত করুন।

উদাহরণ:

CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>(List.of("One", "Two"));
for (String item : list) {
    if ("Two".equals(item)) {
        list.add("Three"); // নিরাপদ
    }
}
System.out.println(list); // [One, Two, Three]

৫. প্রযোজক-গ্রাহক প্যাটার্নে BlockingQueue ব্যবহার করুন

  • BlockingQueue যেমন ArrayBlockingQueue বা LinkedBlockingQueue ব্যবহার করুন থ্রেড সিঙ্ক্রোনাইজেশনের জন্য।
  • put() এবং take() মেথড ব্লক করে কিউ পূর্ণ বা খালি থাকলে।

উদাহরণ:

BlockingQueue<Integer> queue = new ArrayBlockingQueue<>(10);

// প্রযোজক থ্রেড
Thread producer = new Thread(() -> {
    try {
        for (int i = 1; i <= 10; i++) {
            queue.put(i);
            System.out.println("Produced: " + i);
        }
    } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
    }
});

// গ্রাহক থ্রেড
Thread consumer = new Thread(() -> {
    try {
        while (true) {
            Integer value = queue.take();
            System.out.println("Consumed: " + value);
        }
    } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
    }
});

producer.start();
consumer.start();

৬. CopyOnWriteArrayList এড়িয়ে চলুন যদি লেখার অপারেশন বেশি হয়

  • CopyOnWriteArrayList প্রতিবার লেখার সময় একটি নতুন কপি তৈরি করে। রাইট-ইনটেনসিভ অপারেশন থাকলে এটি এড়িয়ে চলুন।

পরিবর্তে ব্যবহার করুন:

  • Collections.synchronizedList() বা নিজস্ব সিঙ্ক্রোনাইজড স্ট্রাকচার তৈরি করুন।

৭. ক্যাশের জন্য ConcurrentHashMap ব্যবহার করুন

  • ক্যাশ মেকানিজম তৈরির জন্য ConcurrentHashMap ব্যবহার করুন এবং অপারেশনাল মেথড (যেমন computeIfAbsent) ব্যবহার করুন।

উদাহরণ:

ConcurrentHashMap<String, String> cache = new ConcurrentHashMap<>();

String value = cache.computeIfAbsent("Key", key -> "ComputedValue");
System.out.println(value); // ComputedValue

৮. Thread-Safe Queue ব্যবহার করুন

  • PriorityBlockingQueue বা DelayQueue ব্যবহার করুন থ্রেড-সেফ কিউ ম্যানেজমেন্টের জন্য।

উদাহরণ:

import java.util.concurrent.DelayQueue;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;

class DelayedTask implements Delayed {
    private final long delayTime;
    private final long creationTime;

    public DelayedTask(long delayInMilliseconds) {
        this.delayTime = delayInMilliseconds;
        this.creationTime = System.currentTimeMillis();
    }

    @Override
    public long getDelay(TimeUnit unit) {
        long diff = (creationTime + delayTime) - System.currentTimeMillis();
        return unit.convert(diff, TimeUnit.MILLISECONDS);
    }

    @Override
    public int compareTo(Delayed o) {
        return Long.compare(this.getDelay(TimeUnit.MILLISECONDS), o.getDelay(TimeUnit.MILLISECONDS));
    }
}

public class DelayQueueExample {
    public static void main(String[] args) throws InterruptedException {
        DelayQueue<DelayedTask> delayQueue = new DelayQueue<>();
        delayQueue.put(new DelayedTask(2000));
        System.out.println("Task added to delay queue. Waiting...");

        DelayedTask task = delayQueue.take(); // Waits until delay expires
        System.out.println("Task executed!");
    }
}

৯. পারফরম্যান্স মনিটর করুন

  • Concurrent Collections ব্যবহার করার সময় জাভা প্রোফাইলিং টুল (যেমন JVisualVM) দিয়ে পারফরম্যান্স যাচাই করুন।
  • বেশি সংখ্যক থ্রেড বা বড় ডেটা ব্যবস্থাপনায় ব্লকিং এবং নন-ব্লকিং পারফরম্যান্স তুলনা করুন।

১০. ডেডলক এবং লাইভলক এড়ান

  • একাধিক থ্রেড থেকে একই রিসোর্সে অ্যাক্সেস করার সময় ডেডলক এড়ানোর জন্য যথাযথ থ্রেড সিঙ্ক্রোনাইজেশন ব্যবহার করুন।
  • সর্বদা নির্দিষ্ট অর্ডারে রিসোর্স অ্যাক্সেস নিশ্চিত করুন।

  • ConcurrentHashMap এবং BlockingQueue থ্রেড-সেফ অপারেশনের জন্য দ্রুত এবং কার্যকর।
  • CopyOnWriteArrayList রিড-ইনটেনসিভ পরিবেশে পারফেক্ট।
  • সর্বদা থ্রেড-সেফ কালেকশনের সঠিক ব্যবহার নিশ্চিত করুন এবং সিঙ্ক্রোনাইজেশন জটিলতা এড়াতে চেষ্টা করুন।
Content added By
Promotion

Are you sure to start over?

Loading...