জাভাতে বিভিন্ন ধরণের থ্রেড-নিরাপদ সেট


135

জাভাতে থ্রেড-সেফ সেটগুলি তৈরি করার জন্য অনেকগুলি বিভিন্ন বাস্তবায়ন এবং উপায় রয়েছে বলে মনে হচ্ছে। কিছু উদাহরণ অন্তর্ভুক্ত

1) কপিরাইটঅনরাইটআররেসেট

2) সংগ্রহ.সিনক্রোনাইজড সেট (সেট সেট)

3) সমকালীনস্কিপলিস্টসেট

4) সংগ্রহ.নিউসেটফ্র্যামম্যাপ (নতুন কনকন্টারহ্যাশম্যাপ ())

5) অন্যান্য সেট (4) এর মতো উপায়ে উত্পন্ন

এই উদাহরণগুলি কনকুরન્સી প্যাটার্ন থেকে এসেছে : জাভা 6 এ সমবর্তী সেট প্রয়োগকরণ

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

উত্তর:


206

1) CopyOnWriteArraySetএটি একটি বেশ সহজ বাস্তবায়ন - এটির মূলত একটি অ্যারেতে উপাদানগুলির একটি তালিকা থাকে এবং তালিকাটি পরিবর্তন করার সময় এটি অ্যারের অনুলিপি করে। পাঠক এবং লেখকদের মধ্যে সমন্বয় সাধনের প্রয়োজনীয়তা এড়িয়ে (বর্তমানে লেখাকে নিজেই সিঙ্ক্রোনাইজ করা দরকার) - এই সময়ে চলমান আইট্রেটিস এবং অন্যান্য অ্যাক্সেসগুলি পুরানো অ্যারের সাথে অবিরত রয়েছে। সাধারণত দ্রুত সেট অপারেশনগুলি (বিশেষত contains()) এখানে বেশ ধীর গতির হয়, কারণ অ্যারেগুলি লিনিয়ার সময়ে অনুসন্ধান করা হবে।

এটি কেবলমাত্র ছোট সেটগুলির জন্য ব্যবহার করুন যা প্রায়শই পড়বে (পুনরাবৃত্তি হবে) এবং খুব কমই পরিবর্তিত হবে। (শোনার শ্রোতা-সেটগুলি উদাহরণ হতে পারে, তবে এগুলি প্রকৃতপক্ষে সেট নয় এবং এটি কেবল ইডিটি থেকে ব্যবহার করা উচিত))

2) Collections.synchronizedSetমূল সেটটির প্রতিটি পদ্ধতির চারপাশে কেবল একটি সিঙ্ক্রোনাইজড-ব্লক মোড়ানো হবে। আপনার সরাসরি আসল সেটটি অ্যাক্সেস করা উচিত নয়। এর অর্থ হ'ল সেটটির কোনও দুটি পদ্ধতি একই সাথে সম্পাদন করা যাবে না (অন্যটি শেষ না হওয়া অবধি একটি ব্লক করবে) - এটি থ্রেড-নিরাপদ, তবে যদি একাধিক থ্রেড সত্যিই সেটটি ব্যবহার করে থাকে তবে আপনার সম্মতি থাকবে না। যদি আপনি পুনরুক্তি ব্যবহার করে থাকেন তবে পুনরাবৃত্তকারী কলগুলির মধ্যে সেটটি সংশোধন করার সময় আপনার সাধারণত কনকেনারমোডিফিকেশন অনুভূতিগুলি এড়াতে বাহ্যিকভাবে সিঙ্ক্রোনাইজ করতে হবে। পারফরম্যান্সটি আসল সেটটির পারফরম্যান্সের মতো হবে (তবে কিছু সংশ্লেষনের ওভারহেড সহ, এবং যদি একই সাথে ব্যবহার করা হয় তবে ব্লক করা হবে)।

আপনার যদি কেবল স্বল্প সামঞ্জস্য থাকে এবং এটি নিশ্চিত করতে চান যে সমস্ত পরিবর্তনগুলি অন্যান্য থ্রেডের সাথে সাথেই দৃশ্যমান।

3) ও (লগ এন) এর বেশিরভাগ বুনিয়াদি ক্রিয়াকলাপ সহ ConcurrentSkipListSetএকযোগে SortedSetবাস্তবায়ন। এটি একযোগে যুক্ত / অপসারণ এবং পড়ার / পুনরাবৃত্তির অনুমতি দেয়, যেখানে পুনরাবৃত্তি পুনরুক্তিটি তৈরি হওয়ার পর থেকে পরিবর্তনগুলি সম্পর্কে বলতে বা নাও বলতে পারে। বাল্ক অপারেশনগুলি কেবল একাধিক একক কল, এবং পরমাণুভাবে নয় - অন্যান্য থ্রেডগুলি কেবল তাদের কয়েকটি পর্যবেক্ষণ করতে পারে।

স্পষ্টতই আপনি এটি ব্যবহার করতে পারেন কেবল যদি আপনার উপাদানগুলিতে কিছু মোট অর্ডার থাকে। এটি উচ্চ-সহনীয় পরিস্থিতিতে, খুব বেশি সংখ্যক বড় সেট (ও (লগ এন) এর কারণে) জন্য আদর্শ প্রার্থীর মতো দেখাচ্ছে।

4) ConcurrentHashMap(এবং এটি থেকে উত্পন্ন সেট) এর জন্য: এখানে সর্বাধিক প্রাথমিক বিকল্পগুলি hashCode()হ্যাশম্যাপ / এর মতো ও (1) এ (তবে আপনার যদি ভাল এবং দ্রুত থাকে তবে) (তবে ও (এন) এর অধঃপতন হতে পারে) are HashSet। লেখার জন্য একটি সীমাবদ্ধ চুক্তি রয়েছে (টেবিলটি বিভক্ত করা হয়েছে, এবং লেখার অ্যাক্সেস প্রয়োজনীয় পার্টিশনে সিঙ্ক্রোনাইজ করা হবে), যখন পঠনের অ্যাক্সেস পুরোপুরি নিজের এবং লেখার থ্রেডের সাথে সামঞ্জস্যপূর্ণ (তবে সম্ভবত বর্তমানে পরিবর্তনের ফলাফলগুলি দেখতে পাবে না) লিখিত)। পুনরুক্তিকারীটি তৈরি হওয়ার পর থেকে পরিবর্তনগুলি দেখতে পারে এবং নাও দেখতে পারে এবং বাল্ক অপারেশনগুলি পারমাণবিক নয়। আকার পরিবর্তন ধীর (হ্যাশম্যাপ / হ্যাশসেট হিসাবে), সুতরাং এটি তৈরির প্রয়োজনীয় আকারটি নির্ধারণ করে এটিকে এড়িয়ে চলার চেষ্টা করুন (এবং এর প্রায় 1/3 অংশ ব্যবহার করুন, 3/4 পূর্ণ হওয়ার পরে এটি আকার পরিবর্তন করে)।

আপনার যখন বড় সেট থাকে, একটি ভাল (এবং দ্রুত) হ্যাশ ফাংশন থাকে তখন এটি ব্যবহার করুন এবং মানচিত্র তৈরির আগে সেট আকার এবং প্রয়োজনীয় সংমিশ্রণের অনুমান করতে পারবেন।

৫) এখানে ব্যবহার করা যেতে পারে এমন আরও একসাথে মানচিত্রের প্রয়োগ রয়েছে?


1
কেবলমাত্র 1 এ দর্শন সংশোধন), নতুন অ্যারেতে অনুলিপি করার প্রক্রিয়াটি সিঙ্ক্রোনাইজ করে অবশ্যই লকড করে দিতে হবে। অতএব, অনুলিপি সংকলনের প্রয়োজনীয়তা অনুলিপি করে অনুলিপি করুন অনুলিপিআরএরেটসেট।
ক্যাপ্টেনহাস্টিংস

ConcurrentHashMapভিত্তিক সেট উপর ভিত্তি করে, "এভাবে তৈরির জন্য প্রয়োজনীয় আকার নির্ধারণ করে এড়াতে চেষ্টা করুন।" মানচিত্রটিতে আপনি যে আকার দেবেন তা আপনার অনুমানের (বা জ্ঞাত মান) থেকে 33% এর বেশি হওয়া উচিত, যেহেতু সেটটি 75% লোডে সেট করে। আমি ব্যবহার করিexpectedSize + 4 / 3 + 1
ডেরেন

@ ড্যারেন আমি অনুমান করি প্রথমটি +কী বোঝানো হয়েছে *?
পাওলো ইবারম্যান

@ পাওলোএবারম্যান অবশ্যই ... এটি হওয়া উচিতexpectedSize * 4 / 3 + 1
ড্যারেন

1
জন্য ConcurrentMap(বাHashMap ) জাভা 8 যদি একই বালতি পৌছানোর থ্রেশহোল্ড মান ম্যাপিং এন্ট্রি নম্বর (আমি বিশ্বাস করি 16 থাকে) তাহলে তালিকা একটি বাইনারি অনুসন্ধান বৃক্ষ পরিবর্তিত পরার মধ্যে (লাল-কালো গাছ precised করা হবে) এবং যে ক্ষেত্রে বর্ণন আপ সময় হবে O(lg n)এবং না O(n)
akhil_mittal

20

প্রতিটি সংশোধন করে পুরো সেটটি ব্যবহার করে এবং এর পরিবর্তে সম্মতি সম্পর্কিত বৈশিষ্ট্যগুলির সাথে contains()পারফরম্যান্সকে একত্রিত করা সম্ভব ।HashSetCopyOnWriteArraySetAtomicReference<Set>

বাস্তবায়ন স্কেচ:

public abstract class CopyOnWriteSet<E> implements Set<E> {

    private final AtomicReference<Set<E>> ref;

    protected CopyOnWriteSet( Collection<? extends E> c ) {
        ref = new AtomicReference<Set<E>>( new HashSet<E>( c ) );
    }

    @Override
    public boolean contains( Object o ) {
        return ref.get().contains( o );
    }

    @Override
    public boolean add( E e ) {
        while ( true ) {
            Set<E> current = ref.get();
            if ( current.contains( e ) ) {
                return false;
            }
            Set<E> modified = new HashSet<E>( current );
            modified.add( e );
            if ( ref.compareAndSet( current, modified ) ) {
                return true;
            }
        }
    }

    @Override
    public boolean remove( Object o ) {
        while ( true ) {
            Set<E> current = ref.get();
            if ( !current.contains( o ) ) {
                return false;
            }
            Set<E> modified = new HashSet<E>( current );
            modified.remove( o );
            if ( ref.compareAndSet( current, modified ) ) {
                return true;
            }
        }
    }

}

আসলে AtomicReferenceমানটি অস্থির হিসাবে চিহ্নিত করে। এর অর্থ এটি নিশ্চিত করে যে কোনও থ্রেড বাসি ডেটা পড়ছে না এবং happens-beforeগ্যারান্টি সরবরাহ করে কারণ কোডটি সংকলক দ্বারা পুনরায় সাজানো যায় না। তবে যদি কেবলমাত্র পেতে / সেট পদ্ধতি AtomicReferenceব্যবহার করা হয় তবে আমরা বাস্তবে অভিনব উপায়ে আমাদের পরিবর্তনশীল অস্থির চিহ্নিত করছি।
akhil_mittal

এই উত্তরটি যথেষ্ট পরিমাণে উত্সাহিত করা যায় না কারণ (1) যদি আমি কিছু মিস না করি তবে এটি সমস্ত সংগ্রহের ধরণের জন্য কাজ করবে (2) অন্য শ্রেণীর কোনওটিই পুরো সংগ্রহটিকে একবারে একত্রে আপডেট করার উপায় সরবরাহ করে না ... এটি খুব দরকারী ।
গিলি

আমি এই ভারব্যাটিমটি বরাদ্দ দেওয়ার চেষ্টা করেছি তবে abstractবেশ কয়েকটি পদ্ধতি লিখতে না পারার জন্য এটি লেবেলযুক্ত বলে মনে হয়েছিল । আমি তাদের কিন্তু দৌড়ে সঙ্গে একটি রোডব্লক মধ্যে যোগ সম্পর্কে সেট iterator()। মডেলটি না ভেঙে এই জিনিসটির উপরে কীভাবে একজন পুনরুক্তি বজায় রাখতে হয় তা আমি জানি না। দেখে মনে হচ্ছে আমাকে সবসময়ই যেতে হবে refএবং প্রতিবারই অন্যরকম অন্তর্নিহিত সেট পাওয়া যেতে পারে, যার জন্য অন্তর্নিহিত সেটে একটি নতুন পুনরাবৃত্তকারী পাওয়া দরকার যা আমার পক্ষে অকেজো, কারণ এটি আইটেম শূন্য দিয়ে শুরু হবে। কোন অন্তর্দৃষ্টি?
nclark

ঠিক আছে, আমি গ্যারান্টিটি অনুমান করি, প্রতিটি গ্রাহক সময়মতো একটি নির্দিষ্ট স্ন্যাপশট পান, সুতরাং অন্তর্নিহিত সংগ্রহের পুনরুক্তিটি যদি আপনার প্রয়োজন হয় তবে এটি ঠিক কাজ করবে। আমার ব্যবহারের ক্ষেত্রে প্রতিযোগিতামূলক থ্রেডগুলিকে এতে পৃথক সংস্থানগুলি "দাবি" করার অনুমতি দেওয়া এবং সেগুলির বিভিন্ন সংস্করণ থাকলে সেগুলি কাজ করবে না। সেকেন্ডে যদিও ... আমার ধারণা আমার থ্রেডটিতে কেবল নতুন পুনরাবৃত্তির দরকার হবে এবং যদি কপিঅনওয়ারাইটসেট.রিমোভ (নির্বাচিত_ইটিম) মিথ্যা প্রত্যাবর্তন করে তবে আবার চেষ্টা করুন ... যা এটিকে নির্বিশেষে করতে হবে :)
nclark

11

জাভাডোকগুলি যদি সহায়তা না করে, আপনার সম্ভবত ডেটা স্ট্রাকচারগুলি পড়ার জন্য কোনও বই বা নিবন্ধ সন্ধান করা উচিত। এক পলকে:

  • আপনি যখনই সংগ্রহটি পরিবর্তন করবেন প্রতিবার কপিরাইটঅনরাইটআরয়েসেট অন্তর্নিহিত অ্যারের একটি নতুন অনুলিপি তৈরি করে, তাই লেখাগুলি ধীর হয় এবং আইট্রেটারগুলি দ্রুত এবং সামঞ্জস্যপূর্ণ।
  • কালেকশনস.সিনক্রোনাইজড সেট () থ্রেডসেফ সেট সেট করতে পুরানো স্কুল সিঙ্ক্রোনাইজড মেথড কল ব্যবহার করে। এটি একটি স্বল্প-সম্পাদনকারী সংস্করণ হবে।
  • কনক্র্যান্টস্কিপলিস্টসেটটি বেমানান ব্যাচের ক্রিয়াকলাপ (অ্যাডএল, রিমুভাল অল ইত্যাদি) এবং আইট্রেটারদের সাথে পারফর্ম্যান্ট লেখার প্রস্তাব দেয়।
  • কালেকশনস.ইনওসেটফ্র্যামম্যাপ (নতুন কনকন্টারহ্যাশম্যাপ ()) এর কনকন্টেনার হ্যাশম্যাপের শব্দার্থক শব্দ রয়েছে, যা আমি বিশ্বাস করি যে পড়া বা লেখার জন্য প্রয়োজনীয়ভাবে অনুকূল নয়, তবে কনকন্টারস্কিপলিস্টসেটের মতো, বেমানান ব্যাচের ক্রিয়াকলাপ রয়েছে।


1

দুর্বল উল্লেখগুলির সমবর্তী সেট c

আরেকটি মোড় দুর্বল উল্লেখগুলির একটি থ্রেড-নিরাপদ সেট ।

পাব-সাব দৃশ্যে গ্রাহকদের ট্র্যাক করার জন্য এই জাতীয় সেট কার্যকর । যখন কোনও গ্রাহক অন্য স্থানে সুযোগের বাইরে চলে যায়, এবং তাই আবর্জনা সংগ্রহের প্রার্থী হওয়ার দিকে এগিয়ে যায়, গ্রাহককে নিখুঁতভাবে সদস্যতা ছাড়াই বিরক্ত করার দরকার নেই। দুর্বল রেফারেন্স গ্রাহককে আবর্জনা সংগ্রহের প্রার্থী হওয়ার পরিবর্তনে এটি সম্পূর্ণ করতে দেয়। অবশেষে আবর্জনা সংগ্রহ করা হলে সেটে প্রবেশটি সরানো হয়।

যদিও এরূপ কোনও সেট সরাসরি বান্ডিল ক্লাসগুলির সাথে সরবরাহ করা হয়নি, আপনি কয়েকটি কল দিয়ে একটি তৈরি করতে পারেন।

প্রথমে আমরা ক্লাসটি কাজে Setলাগিয়ে দুর্বল রেফারেন্স দিয়ে শুরু করি WeakHashMap। এটি ক্লাস ডকুমেন্টেশনের জন্য দেখানো হয়েছে Collections.newSetFromMap

Set< YourClassGoesHere > weakHashSet = 
    Collections
    .newSetFromMap(
        new WeakHashMap< YourClassGoesHere , Boolean >()
    )
;

মূল্য মানচিত্রের, Boolean, অপ্রাসঙ্গিক এখানে হিসাবে কী মানচিত্রের আপ আমাদের করে তোলে Set

গ্রাহকগণ এবং প্রকাশকরা পৃথক থ্রেডে কাজ করছেন (সম্ভবতঃ সম্ভবত কেসটি) তবে পব-সাব-এর মতো দৃশ্যে আমাদের থ্রেড-সুরক্ষা দরকার।

এই সেটটি থ্রেড-নিরাপদ করতে সিঙ্ক্রোনাইজড সেট হিসাবে মোড়কে আরও এক ধাপ এগিয়ে যান। একটি কল মধ্যে ফিড Collections.synchronizedSet

this.subscribers =
        Collections.synchronizedSet(
                Collections.newSetFromMap(
                        new WeakHashMap <>()  // Parameterized types `< YourClassGoesHere , Boolean >` are inferred, no need to specify.
                )
        );

এখন আমরা আমাদের ফলাফলগুলি থেকে গ্রাহকদের যোগ করতে এবং অপসারণ করতে পারি Set। এবং কোনও "অদৃশ্য" গ্রাহক অবশেষে আবর্জনা-সংগ্রহের মৃত্যুর পরে স্বয়ংক্রিয়ভাবে সরানো হবে। যখন এই কার্যকর করা হয় আপনার জেভিএমের আবর্জনা-সংগ্রহকারী বাস্তবায়নের উপর নির্ভর করে এবং এই মুহুর্তে রানটাইম পরিস্থিতি নির্ভর করে। কখন এবং কীভাবে অন্তর্নিহিত WeakHashMapমেয়াদোত্তীর্ণ এন্ট্রিগুলি সাফ করে দেয় তার আলোচনা এবং উদাহরণের জন্য এই প্রশ্নটি দেখুন, * WeakHashMap কি ক্রমবর্ধমান, বা এটি আবর্জনার চাবিগুলি পরিষ্কার করে দেয়? *

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.