2017-08-11 125 views
1

我在iOS開發人員角色的面試中被問到這個問題。如何在swift中使用協議實現併發線程?

// Please design a read-write task queue where you can tag the reader task with label, 
// where the the task with the same label should be executed sequentially, and the 
// tasks with different labels could be executed concurrently. However, the writer 
// would get the exclusive access where no concurrent task would happen at the 
// same time with the writer task 

// For example: 
protocol ConcurrentQueueWithSerialization { 
    // Submits a labeled task. 
    // All tasks with the same label will be serialized. 
    // Tasks with different labels will run concurrently. 
    // Use this method to submit a "read" operation from a particular reader. 
    func async(with label: String, task: @escaping() -> Void) 

    // Submits a task that will run concurrently with all other tasks regardless of their labels. 
    func async(task: @escaping() -> Void) 

    // Submits a labeled and delayed task. 
    func asyncAfter(deadline: DispatchTime, with label: String, task: @escaping() -> Void) 

    // Submits an unlabeled and delayed task. 
    func asyncAfter(deadline: DispatchTime, task: @escaping() -> Void) 

    // Submits a barrier task. Only one barrier task is allowed to run at a time. 
    // Works as a critical section for the queue. 
    // Use this method to submit a writer task. 
    func asyncBarrier(task: @escaping() -> Void) 
} 

class MyDispatchQueue: ConcurrentQueueWithSerialization { 
    //TODO: write your implementation 

} 

訪問者要求我在MyDispatchQueue類中實現上述協議。我試過但找不到解決方案。請幫幫我。提前致謝。

+0

SO不是代碼寫入服務。你有什麼嘗試?你遇到了什麼問題? – Alexander

+0

你的問題只包含要求 - 它並沒有顯示你方的努力來解決這個問題。請將您的嘗試加入這個問題 - 因爲本網站不是免費的「我們做您的(家)工作」服務。除此之外:請轉到[幫助]瞭解如何/在這裏問什麼。謝謝! – GhostCat

回答

6

以前我建議使用目標隊列,但更好的是,創建主併發隊列,然後爲指定隊列創建串行隊列,然後通過該主併發隊列分派所有內容。與目標隊列方法不同,這將遵守調度到命名隊列的任務的調度以及派發到未命名隊列的任務。

在這個實現中,下面是一個示例(一個工具「興趣點」配置文件),其中我添加了名爲「fred」和「ginger」的隊列的任務,還添加了一個未命名的隊列,然後我增加了一個屏障任務,然後再向上述每個隊列添加兩個任務。

enter image description here

正如你所看到的,它尊重命名的隊列的串行特性,無名隊列是併發的,而所有這些隊列是同時相對於彼此,但障礙是所有的障礙隊列。

class MyDispatchQueue: ConcurrentQueueWithSerialization { 
    private var namedQueues = [String: DispatchQueue]() 
    private var queue = DispatchQueue(label: Bundle.main.bundleIdentifier! + ".target", attributes: .concurrent) 
    private let lock = NSLock() 

    private func queue(with label: String) -> DispatchQueue { 
     lock.lock() 
     defer { lock.unlock() } 

     if let queue = namedQueues[label] { return queue } 

     let queue = DispatchQueue(label: Bundle.main.bundleIdentifier! + "." + label) 
     namedQueues[label] = queue 
     return queue 
    } 

    func async(with label: String, task: @escaping() -> Void) { 
     queue.async { 
      self.queue(with: label).sync(execute: task) 
     } 
    } 

    func async(task: @escaping() -> Void) { 
     queue.async(execute: task) 
    } 

    func asyncAfter(deadline: DispatchTime, with label: String, task: @escaping() -> Void) { 
     queue.asyncAfter(deadline: deadline) { 
      self.queue(with: label).sync(execute: task) 
     } 
    } 

    func asyncAfter(deadline: DispatchTime, task: @escaping() -> Void) { 
     queue.asyncAfter(deadline: deadline, execute: task) 
    } 

    func asyncBarrier(task: @escaping() -> Void) { 
     queue.async(flags: .barrier, execute: task) 
    } 
} 

注意,我也同步訪問namedQueues陣列,以保證這個類的線程安全。