/// Using this class for safe access dictionary value when working with multi thread
public final class SafeDictionary<Key: Hashable, Value> {
fileprivate let concurrentQueue = DispatchQueue(label: "com.SafeArray", attributes: .concurrent)
fileprivate var dictionary: [Key: Value] = [:]
public var keys: Dictionary<Key, Value>.Keys {
return dictionary.keys
}
public subscript(key: Key) -> Value? {
get {
getValue(key: key)
}
set(newValue) {
if let value = newValue {
updateValue(value, forKey: key)
} else {
removeValue(forKey: key)
}
}
}
public func getValue(key: Key) -> Value? {
var valueOfKey: Value?
concurrentQueue.sync {
valueOfKey = dictionary[key]
}
return valueOfKey
}
public func updateValue(_ value: Value, forKey: Key) {
concurrentQueue.async(flags: .barrier) { [weak self] in
guard let `self` = self else { return }
self.dictionary.updateValue(value, forKey: forKey)
}
}
public func removeValue(forKey key: Key) {
concurrentQueue.async(flags: .barrier) { [weak self] in
guard let `self` = self else { return }
self.dictionary.removeValue(forKey: key)
}
}
public func removeAll(keepingCapacity: Bool = false) {
concurrentQueue.async(flags: .barrier) { [weak self] in
guard let `self` = self else { return }
self.dictionary.removeAll(keepingCapacity: keepingCapacity)
}
}
}
验证SafeArray和SafeDictionary的写法是否正确
private func concurrentDic() {
let start = Date().timeIntervalSince1970
/// 使用线程安全字典
let dict = SafeDictionary<Int, Any>()
let requestCount = SafeDictionary<String, Int>()
/// 使用常规字典
// var dict = [Int: Int]()
// var requestCount: [String : Int] = [:]
var diterations = 1000
DispatchQueue.concurrentPerform(iterations: 1000) { index in
dict.updateValue(diterations, forKey: diterations)
dict[diterations] = diterations
if let reqcount = requestCount["test"] {
if reqcount <= 15 {
requestCount["test"] = (reqcount + 1)
}
} else {
requestCount["test"] = 0
}
DispatchQueue.global().sync {
diterations -= 1
// Final loop
guard diterations <= 10 else { return }
let message = String(format: "Safe loop took %.8f seconds",
Date().timeIntervalSince1970 - start)
print(message)
}
}
}
private func concurrentArr() {
let start = Date().timeIntervalSince1970
/// 使用线程安全数组
let array = SafeArray<Int>()
/// 使用常规数组
// var array = [Int]()
var aiterations = 1000
DispatchQueue.concurrentPerform(iterations: 1000) { index in
let last = array.last ?? 0
array.append(last + 1)
DispatchQueue.global().sync {
aiterations -= 1
// Final loop
guard aiterations <= 0 else { return }
let message = String(format: "Safe loop took %.8f seconds, count: %d.",
Date().timeIntervalSince1970 - start,
array.count)
print(message)
}
}
}
网友评论