Multithreading 异步while循环的设计模式
我有一个函数可以归结为:Multithreading 异步while循环的设计模式,multithreading,macos,asynchronous,grand-central-dispatch,Multithreading,Macos,Asynchronous,Grand Central Dispatch,我有一个函数可以归结为: while(doWork) { config = generateConfigurationForTesting(); result = executeWork(config); doWork = isDone(result); } 假设所有函数都是线程安全的,独立于以前的迭代,并且可能需要比允许的最大线程数更多的迭代,我如何重写它以实现高效的异步执行 这里的问题是,我们不知道需要提前进行多少次迭代,因此我们无法创建dispatch\u组或使用dispat
while(doWork)
{
config = generateConfigurationForTesting();
result = executeWork(config);
doWork = isDone(result);
}
假设所有函数都是线程安全的,独立于以前的迭代,并且可能需要比允许的最大线程数更多的迭代,我如何重写它以实现高效的异步执行
这里的问题是,我们不知道需要提前进行多少次迭代,因此我们无法创建dispatch\u组
或使用dispatch\u apply
这是我第一次尝试,但它看起来有点丑陋,因为我随意选择的价值观和睡眠
int thread_count = 0;
bool doWork = true;
int max_threads = 20; // arbitrarily chosen number
dispatch_queue_t queue =
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
while(doWork)
{
if(thread_count < max_threads)
{
dispatch_async(queue, ^{ Config myconfig = generateConfigurationForTesting();
Result myresult = executeWork();
dispatch_async(queue, checkResult(myresult)); });
thread_count++;
}
else
usleep(100); // don't consume too much CPU
}
void checkResult(Result value)
{
if(value == good) doWork = false;
thread_count--;
}
int线程计数=0;
bool-doWork=true;
int max_threads=20;//任意选择数
调度队列=
调度获取全局队列(调度队列优先级默认为0);
while(嫁妆)
{
if(线程数<最大线程数)
{
dispatch_async(队列,^{Config myconfig=generateConfigurationForTesting();
结果myresult=执行作业();
dispatch_async(queue,checkResult(myresult));});
线程计数++;
}
其他的
usleep(100);//不要消耗太多CPU
}
无效检查结果(结果值)
{
如果(值==良好)doWork=错误;
线程计数--;
}
根据您的描述,它看起来像是一种随机化技术,或者是一种生成器,可以进行几乎无限次的配置(因此您的评论是,您不知道提前需要多少次迭代)。作为一个假设,您基本上只能使用您创建的模型,因为您的执行者需要受到关于队列的一些合理假设的限制,并且您不想过度生成,因为这只会在您成功找到value==good
度量值后延长运行时间
我建议您考虑使用队列(或<代码> OsOxic增量*<代码>和<代码> OsActuiPrimult*>代码>,以保护对<代码> TraceRealCuth< <代码>和<代码> DOWORK 的访问。目前,
thread\u count
递增和递减将发生在两个不同的队列中(主线程的主队列和后台任务的默认队列),因此可以同时递增和递减线程计数。这可能会导致计数不足(这将导致创建的线程数量超出预期)或计数过多(这将导致您永远无法完成任务)
另一个让它看起来更好的选项是让
checkResult
在value!的情况下向队列中添加新元素=好的
。这样,您可以使用dispatch\u apply(20,queue,^{…})
加载队列的初始元素,并且根本不需要thread\u计数。前20个将使用dispatch\u apply
(或dispatch\u apply
认为适合您的配置的金额)添加,然后每次调用checkResult
时,您可以设置doWork=false
或将另一个操作添加到queue
dispatch\u apply()
可以做到这一点,只需将ncpu作为迭代次数传递(apply永远不会使用超过ncpu的工作线程),并在有更多工作要做时保持工作块的每个实例运行(即,循环到GenerateConfiguration for Testing()
,除非!doWork
)。什么是ncpu?假设ncpu是一个大数;您的解决方案使GCD同时运行系统可以处理的尽可能多的线程,并且每个线程作为一个循环运行。找到解决方案后,使用doWork
完成每个线程,然后dispatch\u apply()
中的所有线程都将用完。是吗?很抱歉不清楚,ncpu是系统中的CPU数量,例如从sysctlbyname(“hw.ncpu”,…)
获得。是的,通过这种方法,dispatch\u apply()
基本上是一种让所有CPU反复运行问题直到找到解决方案的有效方法;但它也可能是一种遗传优化的框架。