题目:有十个任务,用三条线程执行,每执行完一个任务去告诉UI还剩几个任务
1. 如果要使用gcd方式创建三个线程,问题见我主页: “异步串行队列"文章
2. 如果采用pthead或者NSthead来创建线程,可以满足创建三个线程要求
3. 先暂且就认为异步执行三个串行队列当作创建了三个线程,队列分别为a, b, c,这个时候10个任务,10个任务如何动态的放在三个队列中呢?
3.a: 平均分布,比如a分配3个任务,b分配3个任务, c分配4个任务;确定就是: 假如a分别的3个任务都需要较长时间执行,这样a在执行第一个任务都没有执行完成的时候,b和c的任务全部执行完了,这样就会造成a的第一个任务都没执行完成,a的后续两个任务继续在a执行,b和c早早的在围观a执行了。
3.b: 动态的分配,gcd是系统完成额并发任务的分配,这里需要自己写逻辑去分配了;初始时先分配任务1到a, 2到b, 3到c, 任务1,2,3 执行完成后取下一个任务到 a, b, c中去执行;这个时候就有问题a, b, c都并发的要想获取下一个任务;这样在一个任务的获取中只能加锁,而加锁又会消耗性能。
4. 暂且当做是要求3个并发去执行,可以用OperationQueue,设置maxConcurremtOperationCount为3;也可以采用gcd + 信号量的方式。
代码如下:
letlabel =UILabel()
label.textColor= .black
label.text="初始10个任务"
label.frame=CGRect.init(x:30, y:100, width:200, height:50)
self.view.addSubview(label)
letsemaphore =DispatchSemaphore(value:3);
varcount =10;
letmutex =NSLock.init()
foriin0...9{
semaphore.wait()
DispatchQueue.global().async{
print("task start", i)
sleep(UInt32(Int.random(in:Range(1...5))))
print("task end", i)
mutex.lock()
count-=1
print("剩下任务数量:", count)
DispatchQueue.main.async{
label.text=String(format:"剩下任务: %d", count)
}
mutex.unlock()
}
semaphore.signal()
}
5. 上面代码把数量更新放在全局队列,需要加锁;由于主队列是串行的,也可以把数量更新的逻辑放在主队列,就不需要加锁;两种选择具体看场景和业务需求;
部分代码如下:
var count = 10
func finishTask() {
print("剩下任务数量:",count)
count-=1
label.text=String(format:"剩下任务: %d",count)
}
DispatchQueue.main.async {
self.finishTask()
}