সমাহার বনাম জিসিডিতে সিরিয়াল সারি


117

আমি জিসিডিতে সমবর্তী এবং সিরিয়াল সারিগুলি সম্পূর্ণরূপে বুঝতে লড়াই করছি। আমার কিছু সমস্যা আছে এবং আশা করছি যে কেউ আমাকে সুস্পষ্টভাবে এবং ঠিক সময়ে উত্তর দিতে পারে।

  1. আমি পড়ছি যে সিরিয়াল সারি তৈরি করা হয় এবং একের পর এক কাজ সম্পাদন করতে ব্যবহৃত হয়। তবে, কী ঘটবে যদি:

    • আমি একটি সিরিয়াল সারি তৈরি
    • dispatch_asyncএ, বি, সি তিনটি ব্লক প্রেরণের জন্য আমি তিনবার ব্যবহার করেছি (সিরিয়াল সারিটিতে আমি তৈরি করেছি) times

    তিনটি ব্লক কার্যকর করা হবে:

    • ক্রম এ, বি, সি ক্রম কারণ সিরিয়াল

      অথবা

    • একযোগে (একই সময়ে parralel থ্রেডে) কারণ আমি ASYNC প্রেরণ ব্যবহার করেছি
  2. আমি পড়ছি যে dispatch_syncএকের পর এক ব্লকগুলি কার্যকর করতে আমি সামনের সারিতে ব্যবহার করতে পারি । সেক্ষেত্রে কেন সিরিয়াল সারিগুলি বিদ্যমান আছে, যেহেতু আমি সর্বদা একটি সমবর্তী কাত ব্যবহার করতে পারি যেখানে আমি চাই যতটা ব্লক সিঙ্ক্রোনোসালি পাঠাতে পারি?

    কোন ভাল ব্যাখ্যা জন্য ধন্যবাদ!


একটি সহজ ভাল পূর্বশর্ত প্রশ্ন প্রেরণ সিঙ্ক বনাম অ্যাসিঙ্ক
মধু

উত্তর:


216

একটি সাধারণ উদাহরণ: আপনার একটি ব্লক রয়েছে যা কার্যকর করতে এক মিনিট সময় নেয়। আপনি এটিকে মূল থ্রেড থেকে একটি সারিতে যুক্ত করুন। চারটি মামলার দিকে নজর দেওয়া যাক।

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

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


14
সুতরাং আপনি আমাকে বলছেন যে: (1) সারিটির ধরণ (সংক্ষিপ্ত বা সিরিয়াল) কেবলমাত্র উপাদান যা সিদ্ধান্ত নিয়েছে যে কার্যগুলি ক্রমানুসারে চালানো হয়েছে বা প্যারালেলে ;; (২) প্রেরণের ধরণ (সিঙ্ক বা অ্যাসিঙ্ক) কেবলমাত্র এটিই বলেছে যে মৃত্যুদন্ড কার্যকর হয় বা পরবর্তী নির্দেশিকায় যায় না? মানে, যদি আমি কোনও কাজ SYNC প্রেরণ করি তবে কোডগুলি যে কাজগুলি শেষ না হওয়া অবধি ব্লক হয়ে যাবে, তাতে কোন সারি কার্যকর করা হয়নি?
বোগদান আলেকজান্দ্রু

13
নিবন্ধন করুন কীভাবে ব্লকটি সারি করে না তা নয়, সারণি কার্যকর করার নীতি নির্ধারণ করে। সিঙ্কটি ব্লকটি সম্পূর্ণ হওয়ার জন্য অপেক্ষা করে, অ্যাসিঙ্ক দেয় না।
জানো

2
@ সুইফটবাটার একটি নির্দিষ্ট পয়েন্ট পর্যন্ত, হ্যাঁ। আপনি যখন একটি সারি তৈরি করেন আপনি সর্বাধিক সংখ্যক থ্রেড নির্দিষ্ট করতে পারেন। আপনি যদি এর চেয়ে কম কাজ যোগ করেন তবে তারা সমান্তরালে কার্যকর করবে। এর চেয়ে আরও বেশি কিছু রয়েছে, সক্ষমতা উপলব্ধ না হওয়া পর্যন্ত কিছু কাজ একটি সারিতে থাকবে।
স্টিফেন ডার্লিংটন

2
@ পাবলোএ।, মূল থ্রেড একটি সিরিয়াল সারি তাই কেবলমাত্র দুটি ক্ষেত্রে রয়েছে। এর বাইরেও ঠিক একই রকম। অ্যাসিঙ্ক তত্ক্ষণাত্ ফিরে আসে (এবং সম্ভবত বর্তমান রান লুপের শেষে ব্লকটি কার্যকর করা হবে)। প্রধান gotcha হয় যদি আপনি সিঙ্ক করতে হয় থেকে মূল থ্রেড থেকে মূল থ্রেড, যে ক্ষেত্রে আপনি একটি অচলাবস্থা পেতে।
স্টিফেন ডার্লিংটন

1
@ শৌকেতশেখ নং মূল থ্রেড একটি ক্রমিক সারি, তবে সমস্ত ক্রমিক সারি মূল থ্রেড নয়। চতুর্থ পয়েন্টে, মূল থ্রেডটি ব্লক হয়ে যাবে, অন্য থ্রেডটির কাজটির প্রতিযোগিতার জন্য অপেক্ষা করছে। যদি সিরিয়াল সারিটি মূল থ্রেড হত তবে আপনি একটি অচলাবস্থা পেয়ে যাবেন।
স্টিফেন ডার্লিংটন

122

এখানে পরীক্ষায় যে আমি আমাকে এই সম্পর্কে বোঝাতে করেছি একটি দম্পতি আছে serial, concurrentসঙ্গে লাইনে দাঁড়িয়ে থাকতো Grand Central Dispatch

 func doLongAsyncTaskInSerialQueue() {

   let serialQueue = DispatchQueue(label: "com.queue.Serial")
      for i in 1...5 {
        serialQueue.async {

            if Thread.isMainThread{
                print("task running in main thread")
            }else{
                print("task running in background thread")
            }
            let imgURL = URL(string: "https://upload.wikimedia.org/wikipedia/commons/0/07/Huge_ball_at_Vilnius_center.jpg")!
            let _ = try! Data(contentsOf: imgURL)
            print("\(i) completed downloading")
        }
    }
}

আপনি যখন জিসিডিতে অ্যাসিঙ্ক ব্যবহার করবেন তখন টাস্কটি বিভিন্ন থ্রেডে (মূল থ্রেড ব্যতীত) চলবে। অ্যাসিঙ্ক মানে পরের লাইনটি কার্যকর করুন ব্লকটি কার্যকর না হওয়া পর্যন্ত অপেক্ষা করবেন না যার ফলস্বরূপ মূল থ্রেড এবং মূল সারিটি অবরুদ্ধ নয়। এটির ক্রমিক সারি যেহেতু, সমস্ত ক্রমিক ক্রিয়ায় যুক্ত করা হয় সেই ক্রিয়ায় কার্যকর করা হয় with ক্রমিকভাবে মৃত্যুদন্ড কার্যকর করা টাস্কগুলি সর্বদা ক্যুয়ের সাথে যুক্ত একক থ্রেড দ্বারা একবারে একবার কার্যকর করা হয়।

func doLongSyncTaskInSerialQueue() {
    let serialQueue = DispatchQueue(label: "com.queue.Serial")
    for i in 1...5 {
        serialQueue.sync {
            if Thread.isMainThread{
                print("task running in main thread")
            }else{
                print("task running in background thread")
            }
            let imgURL = URL(string: "https://upload.wikimedia.org/wikipedia/commons/0/07/Huge_ball_at_Vilnius_center.jpg")!
            let _ = try! Data(contentsOf: imgURL)
            print("\(i) completed downloading")
        }
    }
}

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

func doLongASyncTaskInConcurrentQueue() {
    let concurrentQueue = DispatchQueue(label: "com.queue.Concurrent", attributes: .concurrent)
    for i in 1...5 {
        concurrentQueue.async {
            if Thread.isMainThread{
                print("task running in main thread")
            }else{
                print("task running in background thread")
            }
            let imgURL = URL(string: "https://upload.wikimedia.org/wikipedia/commons/0/07/Huge_ball_at_Vilnius_center.jpg")!
            let _ = try! Data(contentsOf: imgURL)
            print("\(i) completed downloading")
        }
        print("\(i) executing")
    }
}

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

func doLongSyncTaskInConcurrentQueue() {
  let concurrentQueue = DispatchQueue(label: "com.queue.Concurrent", attributes: .concurrent)
    for i in 1...5 {
        concurrentQueue.sync {
            if Thread.isMainThread{
                print("task running in main thread")
            }else{
                print("task running in background thread")
            }
            let imgURL = URL(string: "https://upload.wikimedia.org/wikipedia/commons/0/07/Huge_ball_at_Vilnius_center.jpg")!
            let _ = try! Data(contentsOf: imgURL)
            print("\(i) completed downloading")
        }
        print("\(i) executed")
    }
}

আপনি যখন জিসিডি তে সিঙ্ক ব্যবহার করেন তখন মূল থ্রেডে টাস্ক চলতে পারে। সিঙ্ক একটি প্রদত্ত কাতারে একটি ব্লক চালায় এবং এটি সম্পূর্ণ হওয়ার জন্য অপেক্ষা করে যার ফলস্বরূপ মূল থ্রেড বা মূল সারিটি ব্লক করা হয় ince প্রেরিত ব্লকটি সমাপ্ত না হওয়া পর্যন্ত প্রধান সারিটি অপেক্ষা করতে হবে, মূল থ্রেডটি ব্যতীত অন্য সারিতে থাকা ব্লকগুলি প্রক্রিয়া করার জন্য উপলব্ধ থাকবে the মূল সারি T অতএব ব্যাকগ্রাউন্ডের সারিতে কোডটি কার্যকর করার একটি সম্ভাবনা রয়েছে যা মূল থ্রেডে কার্যকর হতে পারে। এটির সমবর্তী সারিতে যেহেতু সারিগুলিতে ক্রম যুক্ত হওয়ার সাথে সাথে কাজগুলি শেষ নাও হতে পারে। তবে সিঙ্ক্রোনাস অপারেশনের সাহায্যে এটি বিভিন্ন থ্রেড দ্বারা প্রক্রিয়াজাত হতে পারে does সুতরাং এটি এটি সিরিয়াল সারি হিসাবে আচরণ করে।

এই পরীক্ষাগুলির সংক্ষিপ্তসার এখানে দেওয়া হল

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

UI সম্পর্কিত টাস্কটি সর্বদা মূল কাতারে প্রেরণ করে মূল থ্রেড থেকে সঞ্চালন করা উচিত hand ছোট হাতের ইউটিলিটিটি DispatchQueue.main.sync/asyncযেখানে নেটওয়ার্ক সম্পর্কিত / ভারী অপারেশনগুলি সর্বদা অবিচ্ছিন্নভাবে করা উচিত যা আপনি কখনও মূল বা পটভূমি ব্যবহার করছেন তা থ্রেড করে না

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

func doMultipleSyncTaskWithinAsynchronousOperation() {
    let concurrentQueue = DispatchQueue(label: "com.queue.Concurrent", attributes: .concurrent)
    concurrentQueue.async {
        let concurrentQueue = DispatchQueue.global(qos: DispatchQoS.QoSClass.default)
        for i in 1...5 {
            concurrentQueue.sync {
                let imgURL = URL(string: "https://upload.wikimedia.org/wikipedia/commons/0/07/Huge_ball_at_Vilnius_center.jpg")!
                let _ = try! Data(contentsOf: imgURL)
                print("\(i) completed downloading")
            }
            print("\(i) executed")
        }
    }
}

সম্পাদনা সম্পাদনা করুন: আপনি এখানে ডেমো ভিডিও দেখতে পারেন


গ্রেট বিক্ষোভের .... পরের লাইনে ব্লক, executes যা অ ব্লক মূল থ্রেড ফলাফল পর্যন্ত অপেক্ষা করবেন না এই জন্যই আপনি একটি পটভূমি থ্রেডে ব্রেকপয়েন্ট ব্যবহার এটি ঝাঁপ দেবে }কারণ এটি ঠিক সেই মুহুর্তে নির্বাহ করা হয় না
মধু

@ এটি অলস আইওএস গাই still আমি এখনও অ্যাসিঙ্ক সমবর্তী এবং অ্যাসিঙ্ক সিরিয়ালের মধ্যে পার্থক্য বুঝতে পারি না। কোনটি ব্যবহারের জড়িত বিষয়টি। তারা উভয়ই ইউআই-তে ঝামেলা না করে পটভূমিতে চলে। এবং আপনি কেন কখনও সিঙ্ক ব্যবহার করবেন? সব কোড সিঙ্ক হয় না। একটার পর অন্যটা?
২৩

1
@ গিটসিঙ্ক অ্যাপ্লিকেশনটি আপনি এখানে
আনিস পরজুলি 웃

@ সেই অলস আইওএস গাই th: এটি করার জন্য ধন্যবাদ। আমি স্ল্যাক সুইফট-ল্যাং-এ পোস্ট করেছি। হতে পারে 👌 আপনি যদি ডিসপ্যাচগ্রুপ এবং ডিসপ্যাচ ওয়ার্কআইটিএম সম্পর্কেও কিছু করতে পারেন। : ডি
ইওনিস্ট

আমি তোমার গত এক, পরীক্ষা আছে concurrentQueue.syncএর doLongSyncTaskInConcurrentQueue(), ফাংশন এটা মূল থ্রেড ছাপে Task will run in different threadসত্য নয় বলে মনে হয়।
গ্যাবলার

54

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

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

serialQueue.async {
    // this is one task
    // it can be any number of lines with any number of methods
}
serialQueue.async {
    // this is another task added to the same queue
    // this queue now has two tasks
}

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

দুটি ধরণের সারি রয়েছে, সিরিয়াল এবং সমবর্তী, তবে সমস্ত সারি একে অপরের সাথে সামঞ্জস্যপূর্ণ । আপনি যে কোনও কোড "পটভূমিতে" চালাতে চান তার অর্থ আপনি এটি অন্য থ্রেড (সাধারণত মূল থ্রেড) সহ একযোগে চালাতে চান to সুতরাং, পাঠানো সারি, সিরিয়াল বা সমবর্তী, তাদের কাজগুলি অন্যান্য সারির সাথে একই সাথে সম্পাদন করে । কোনও ক্রমিক (সিরিয়াল কাতারে) দ্বারা সম্পাদিত সিরিয়ালাইজেশন কেবল সেই একক [সিরিয়াল] প্রেরণের সারিতে থাকা কাজগুলির সাথে করতে হবে (যেমন উপরের উদাহরণে যেখানে একই সিরিয়াল সারির মধ্যে দুটি কাজ রয়েছে; সেই কাজগুলি একের পরে কার্যকর করা হবে) অন্য, একসাথে কখনও না)।

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

let serialQueue = DispatchQueue(label: "serial")

আপনি এর বৈশিষ্ট্যযুক্ত সম্পত্তিটির মাধ্যমে এটিকে একই সাথে তৈরি করতে পারেন:

let concurrentQueue = DispatchQueue(label: "concurrent", attributes: [.concurrent])

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

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

let concurrentQueue = DispatchQueue.global(qos: .default)

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

সারিগুলি প্রেরণের দুটি উপায় রয়েছে: একযোগে এবং অবিচ্ছিন্নভাবে।

SYNC DISPATCHING এর অর্থ হ'ল যেখানে সারিটি প্রেরণ করা হয়েছিল সেই থ্রেডটি (কলিং থ্রেড) সারি প্রেরণের পরে বিরতি দেয় এবং পুনরায় শুরু হওয়ার আগে সম্পাদন শেষ করার জন্য ue কাতার ব্লকের কার্যটির জন্য অপেক্ষা করে। একযোগে প্রেরণ করতে:

DispatchQueue.global(qos: .default).sync {
    // task goes in here
}

ASYNC DISPATCHING এর অর্থ হল যে সারিটি প্রেরণ করার পরে কলিং থ্রেড চলতে থাকে এবং সেই কাতার ব্লকের কার্য সম্পাদনের জন্য অপেক্ষা না করে। অবিচ্ছিন্নভাবে প্রেরণ:

DispatchQueue.global(qos: .default).async {
    // task goes in here
}

এখন কেউ ভাবতে পারে সিরিয়ালে কোনও কাজ সম্পাদন করার জন্য একটি সিরিয়াল সারি ব্যবহার করা উচিত এবং এটি ঠিক ঠিক নয়। সিরিয়ালে একাধিক টাস্ক সম্পাদন করতে একটি সিরিয়াল সারি ব্যবহার করা উচিত, তবে সমস্ত টাস্ক (নিজেরাই বিচ্ছিন্ন) সিরিয়ালে চালানো হয়। এই উদাহরণ বিবেচনা করুন:

whichQueueShouldIUse.syncOrAsync {
    for i in 1...10 {
        print(i)
    }
    for i in 1...10 {
        print(i + 100)
    }
    for i in 1...10 {
        print(i + 1000)
    }
}

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

এই দুটি সারি বিবেচনা করুন, একটি সিরিয়াল এবং একটি সমবর্তী:

let serialQueue = DispatchQueue(label: "serial")
let concurrentQueue = DispatchQueue.global(qos: .default)

বলুন আমরা অ্যাসিঙ্কে দুটি সমবর্তী কাতাগুলি প্রেরণ করেছি:

concurrentQueue.async {
    for i in 1...5 {
        print(i)
    }
}
concurrentQueue.async {
    for i in 1...5 {
        print(i + 100)
    }
}

1
101
2
102
103
3
104
4
105
5

তাদের আউটপুটটি ঝাঁপিয়ে পড়েছে (আশানুরূপ হিসাবে) তবে লক্ষ্য করুন যে প্রতিটি সারি সিরিয়ালে তার নিজস্ব কাজ সম্পাদন করেছে। এটি কনক্যুরেন্সির সর্বাধিক প্রাথমিক উদাহরণ - একই সারিতে ব্যাকগ্রাউন্ডে একই সময়ে দুটি কাজ চলছে। এবার প্রথম সিরিয়ালটি করা যাক:

serialQueue.async {
    for i in 1...5 {
        print(i)
    }
}
concurrentQueue.async {
    for i in 1...5 {
        print(i + 100)
    }
}

101
1
2
102
3
103
4
104
5
105

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

serialQueue.async {
    for i in 1...5 {
        print(i)
    }
}
serialQueue.async {
    for i in 1...5 {
        print(i + 100)
    }
}

1
2
3
4
5
101
102
103
104
105

এবং এটি সিরিয়ালাইজেশনের সবচেয়ে বুনিয়াদি (এবং কেবলমাত্র সম্ভব) উদাহরণ - একই সারিতে ব্যাকগ্রাউন্ডে (মূল থ্রেডে) সিরিয়ালে দুটি কাজ (একের পর এক) চলছে। তবে যদি আমরা তাদের দুটি পৃথক ক্রমিক কাতারে পরিণত করি (কারণ উপরের উদাহরণে তারা একই সারি) তবে তাদের আউটপুটটি আবারও ঝাঁকুনির মধ্যে পড়ে:

serialQueue.async {
    for i in 1...5 {
        print(i)
    }
}
serialQueue2.async {
    for i in 1...5 {
        print(i + 100)
    }
}

1
101
2
102
3
103
4
104
5
105

এবং এটিই আমি বলতে চাইছিলাম যখন আমি বলেছিলাম সমস্ত সারি একে অপরের সাথে সামঞ্জস্যপূর্ণ। এটি একই সাথে তাদের কাজগুলি সম্পাদন করে এমন দুটি সিরিয়াল কাতারে (কারণ তারা পৃথক সারি)। একটি সারিটি অন্যান্য সারিগুলি জানে না বা যত্ন করে না। এখন দুটি সিরিয়াল কাতারে ফিরে যেতে দিন (একই সারির) এবং তৃতীয় সারি যুক্ত করুন, সমবর্তী:

serialQueue.async {
    for i in 1...5 {
        print(i)
    }
}
serialQueue.async {
    for i in 1...5 {
        print(i + 100)
    }
}
concurrentQueue.async {
    for i in 1...5 {
        print(i + 1000)
    }
}

1
2
3
4
5
101
102
103
104
105
1001
1002
1003
1004
1005

এ ধরণের অপ্রত্যাশিত, কেন ক্রমিক সারিবদ্ধ ক্রিয়াকলাপগুলি সঞ্চালনের আগে শেষ হওয়ার অপেক্ষা করেছিল? এটি একমত নয়। আপনার খেলার মাঠ একটি আলাদা আউটপুট প্রদর্শন করতে পারে তবে আমার এটি দেখিয়েছে। এবং এটি এটি দেখিয়েছিল কারণ জিসিডি এর কাজটি তাড়াতাড়ি সম্পাদন করার জন্য আমার সমবর্তী সারির অগ্রাধিকার যথেষ্ট ছিল না। সুতরাং আমি যদি সমস্ত কিছু একই রাখি তবে গ্লোবাল কিউয়ের কিউএস পরিবর্তন করি (এর পরিষেবার মান, যা কেবল কাতারের অগ্রাধিকার স্তর) let concurrentQueue = DispatchQueue.global(qos: .userInteractive), তবে আউটপুটটি প্রত্যাশা অনুযায়ী:

1
1001
1002
1003
2
1004
1005
3
4
5
101
102
103
104
105

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

আমাদের প্রথম মুদ্রণের উদাহরণের মতো দুটি সমবর্তী কাতারে একটি ঝাঁকুনিযুক্ত প্রিন্টআউট (প্রত্যাশার মতো) দেখায়। তাদের সিরিয়ালে ঝরঝরে মুদ্রণের জন্য, আমাদের উভয়কে একই ক্রমিক কাতারে তৈরি করতে হবে (সেই সারির একই উদাহরণ, পাশাপাশি, কেবল একই লেবেল নয়) । তারপরে প্রতিটি কাজ অন্যটির সাথে সম্মানের সাথে সিরিয়ালে চালানো হয়। তবে সিরিয়ালে মুদ্রণের জন্য তাদের আরেকটি উপায় হ'ল তাদের উভয়কে একযোগে রাখা তবে তাদের প্রেরণের পদ্ধতিটি পরিবর্তন করা:

concurrentQueue.sync {
    for i in 1...5 {
        print(i)
    }
}
concurrentQueue.async {
    for i in 1...5 {
        print(i + 100)
    }
}

1
2
3
4
5
101
102
103
104
105

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

এবং এই কারণেই আমরা নিম্নলিখিতটি করতে পারি না:

DispatchQueue.main.sync { ... }

এটি সারি এবং প্রেরণ পদ্ধতির একমাত্র সম্ভাব্য সংমিশ্রণ যা আমরা সম্পাদন করতে পারি না the মূল কাতারে সিঙ্ক্রোনাস প্রেরণ। এবং এর কারণ আমরা কোঁকড়া ধনুর্বন্ধনী মধ্যে কাজ সম্পাদন না করা পর্যন্ত আমরা মূল সারিটি হিমায়িত করতে বলছি ... যা আমরা মূল কাতারে প্রেরণ করেছি, যা আমরা কেবল হিমশীতল করে দিয়েছি। একে ডেডলক বলা হয়। কোনও খেলার মাঠে এটি ক্রিয়াতে দেখতে:

DispatchQueue.main.sync { // stop the main queue and wait for the following to finish
    print("hello world") // this will never execute on the main queue because we just stopped it
}
// deadlock

একটি উল্লেখযোগ্য জিনিস উল্লেখ করার পরে সম্পদ resources যখন আমরা কোনও কাতাকে একটি কার্য দিই, জিসিডি তার অভ্যন্তরীণভাবে পরিচালিত পুল থেকে একটি উপলব্ধ সারি খুঁজে পায়। এই উত্তরটি লেখার ক্ষেত্রে, প্রতি কোষে 64 টি সারি উপলব্ধ। এটি অনেকটা মনে হলেও এগুলি দ্রুত গ্রাস করা যায়, বিশেষত তৃতীয় পক্ষের লাইব্রেরি, বিশেষত ডাটাবেস ফ্রেমওয়ার্কগুলি দ্বারা। এই কারণে, অ্যাপলের সারি ব্যবস্থাপনা সম্পর্কে সুপারিশ রয়েছে (নীচের লিঙ্কগুলিতে উল্লিখিত); এক হচ্ছে:

ব্যক্তিগত সমকালীন সারি তৈরি করার পরিবর্তে বিশ্বব্যাপী একত্রে প্রেরণের জন্য একটি সারিতে কাজ জমা দিন। ক্রমিক কাজগুলির জন্য, আপনার ক্রমিক সারির লক্ষ্যটি বিশ্বব্যাপী সমবর্তী সারির একটিতে সেট করুন। এইভাবে, থ্রেড তৈরির পৃথক সারির সংখ্যা হ্রাস করার সময় আপনি সারিটির ক্রমিক ক্রিয়াকলাপটি বজায় রাখতে পারেন।

এটি করার জন্য, এগুলি তৈরি করার পরিবর্তে আমরা এর আগে তৈরি করেছি (যা আপনি এখনও পারেন), অ্যাপল এই জাতীয় সিরিয়াল সারি তৈরি করার পরামর্শ দেয়:

let serialQueue = DispatchQueue(label: "serialQueue", qos: .default, attributes: [], autoreleaseFrequency: .inherit, target: .global(qos: .default))

আরও পড়ার জন্য, আমি নিম্নলিখিতটি সুপারিশ করছি:

https://developer.apple.com/library/archive/documentation/General/Conceptual/ConcurrencyProgrammingGuide/Introduction/Introduction.html#//apple_ref/doc/uid/TP40008091-CH1-SW1

https://developer.apple.com/documentation/dispatch/dispatchqueue


7

যদি আমি সঠিকভাবে কিভাবে GCD কাজ করে সে সম্পর্কে বুঝতে, আমি মনে করি সেখানে দুই ধরনের হয় DispatchQueue, serialএবং concurrent, একই সময়ে, দুই পথ কেমন আছো DispatchQueueতার কাজ, নিয়োগ প্রাণবধ closure, প্রথম এক async, এবং অন্যান্য হয় sync। এগুলি একসাথে নির্ধারণ করে যে কীভাবে বন্ধ (কার্য) বাস্তবায়িত হয়।

আমি এটি খুঁজে পেয়েছি serialএবং concurrentবোঝাতে চাইছি যে সারিটি কতগুলি থ্রেড ব্যবহার করতে পারে, তার serialঅর্থ একটি, যেখানে concurrentঅনেকগুলি। আর syncasyncমানে কাজের যা থ্রেডে মৃত্যুদন্ড কার্যকর করা হবে, কলার এর থ্রেড বা থ্রেড যে কিউ অন্তর্নিহিত, syncমানে আহ্বানকারী এর থ্রেডে যেহেতু চালানো asyncমানে অন্তর্নিহিত থ্রেডে চলে।

নিম্নলিখিতটি পরীক্ষামূলক কোড যা Xcode খেলার মাঠে চলতে পারে।

PlaygroundPage.current.needsIndefiniteExecution = true
let cq = DispatchQueue(label: "concurrent.queue", attributes: .concurrent)
let cq2 = DispatchQueue(label: "concurent.queue2", attributes: .concurrent)
let sq = DispatchQueue(label: "serial.queue")

func codeFragment() {
  print("code Fragment begin")
  print("Task Thread:\(Thread.current.description)")
  let imgURL = URL(string: "http://stackoverflow.com/questions/24058336/how-do-i-run-asynchronous-callbacks-in-playground")!
  let _ = try! Data(contentsOf: imgURL)
  print("code Fragment completed")
}

func serialQueueSync() { sq.sync { codeFragment() } }
func serialQueueAsync() { sq.async { codeFragment() } }
func concurrentQueueSync() { cq2.sync { codeFragment() } }
func concurrentQueueAsync() { cq2.async { codeFragment() } }

func tasksExecution() {
  (1...5).forEach { (_) in
    /// Using an concurrent queue to simulate concurent task executions.
    cq.async {
      print("Caller Thread:\(Thread.current.description)")
      /// Serial Queue Async, tasks run serially, because only one thread that can be used by serial queue, the underlying thread of serial queue.
      //serialQueueAsync()
      /// Serial Queue Sync, tasks run serially, because only one thread that can be used by serial queue,one by one of the callers' threads.
      //serialQueueSync()
      /// Concurrent Queue Async, tasks run concurrently, because tasks can run on different underlying threads
      //concurrentQueueAsync()
      /// Concurrent Queue Sync, tasks run concurrently, because tasks can run on different callers' thread
      //concurrentQueueSync()
    }
  }
}
tasksExecution()

আশা করি এটি সহায়ক হতে পারে।


7

আমি এই রূপকটি ব্যবহার করে এটি ভাবতে চাই (এখানে মূল চিত্রের লিঙ্কটি রয়েছে ):

বাবার কিছু সাহায্য দরকার

আসুন কল্পনা করুন যে আপনার বাবা থালা রান্না করছে এবং আপনার কাছে এক গ্লাস সোডা রয়েছে। এটি পরিষ্কার করার জন্য আপনি গ্লাসটি আপনার বাবার কাছে নিয়ে এসেছেন, অন্য থালাটির পাশে রেখে।

এখন আপনার বাবা নিজেই থালা বাসনগুলি করছেন, তাই তিনি এক এক করে সেগুলি করতে চলেছেন: আপনার বাবা এখানে সিরিয়াল সারি উপস্থাপন করেছেন

তবে আপনি সেখানে দাঁড়িয়ে এবং এটি পরিষ্কার হয়ে যাওয়ার বিষয়ে সত্যই আগ্রহী নন। সুতরাং, আপনি গ্লাসটি ফেলে দিন এবং আপনার ঘরে ফিরে যান: এটিকে async প্রেরণ বলা হয় । আপনার বাবা তার কাজ শেষ হয়ে গেলে আপনাকে জানাতে পারে বা নাও পারে তবে গুরুত্বপূর্ণ বিষয়টি হ'ল আপনি কাচটি পরিষ্কার হওয়ার জন্য অপেক্ষা করছেন না; আপনি কি করতে আপনার ঘরে ফিরে যান, আপনি জানেন, বাচ্চাদের স্টাফ।

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

এবং অবশেষে বলা যাক আপনার মা আপনার বাবাকে সাহায্য করার সিদ্ধান্ত নিয়েছে এবং খাবারগুলি তৈরিতে তার সাথে যোগ দেয়। এখন তারা কি একই সাথে একাধিক খাবার পরিষ্কার করতে পারে সেহেতু এই সারিটি একযোগে সারি হয়ে উঠেছে ; তবে মনে রাখবেন যে তারা এখনও কীভাবে কাজ করে তা বিবেচনা না করেই আপনি সেখানে অপেক্ষা করতে বা আপনার ঘরে ফিরে যেতে সিদ্ধান্ত নিতে পারেন।

আশাকরি এটা সাহায্য করবে


3

1. আমি পড়ছি যে সিরিয়াল সারি তৈরি করা হয় এবং একের পর এক কাজ সম্পাদনের জন্য ব্যবহৃত হয়। তবে, কী ঘটবে যদি: - • আমি একটি সিরিয়াল সারি তৈরি করি disp আমি তিনবার এ, বি, সি প্রেরণের জন্য প্রেরণ_কেন্দ্র (আমি সদ্য তৈরি সিরিয়াল কাতারে) ব্যবহার করি

উত্তর : - তিনটি ব্লক একের পর এক কার্যকর করা হয়েছে। আমি একটি নমুনা কোড তৈরি করেছি যা বুঝতে সহায়তা করে।

let serialQueue = DispatchQueue(label: "SampleSerialQueue")
//Block first
serialQueue.async {
    for i in 1...10{
        print("Serial - First operation",i)
    }
}

//Block second
serialQueue.async {
    for i in 1...10{
        print("Serial - Second operation",i)
    }
}
//Block Third
serialQueue.async {
    for i in 1...10{
        print("Serial - Third operation",i)
    }
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.