是否有一种方法可以重新启动已完成其任务的线程,从而避免为下一个任务创建新线程的开销? (请注意,所有其他处理器/线程都将处于繁忙状态,并且(not (bt:thread-alive-p thread)
会在线程死时发出信号。)例如,我已经在已完成的线程上尝试了bt:interrupt-thread,但这是行不通的:
* (defparameter *x* 0)
*X*
* (let ((thread (bt:make-thread (lambda () (setf *x* (loop for i from 1 to 10 sum i))))))
(sleep 1)
(print *x*)
(bt:interrupt-thread thread (lambda () (setf *x* (loop for i from 1 to 100 sum i))))
(sleep 1)
(print *x*))
55
debugger invoked on a SB-THREAD:INTERRUPT-THREAD-ERROR in thread
#<THREAD "main thread" RUNNING {10012E0613}>:
Interrupt thread failed: thread #<THREAD "Anonymous thread" FINISHED
values: 55 {1005D410D3}> has exited.
还有,是否有一种方法可以访问传递给bt:make-thread的函数返回的结果(在线程中),以避免像上面的示例那样通过全局变量进行通信?
答案 0 :(得分:2)
完成后就完成了。通常的技术是让线程运行一个循环,等待某种通道上的某些工作。
lparallel或chanl之类的图书馆可能会有很大帮助。
例如,您可以像这样使用chanl
:
(defun parallel-mayhem (fun count)
(let* ((start-chan (make-instance 'chanl:channel))
(results-chan (make-instance 'chanl:channel)))
(loop :repeat count
:do (chanl:pexec ()
(chanl:send start-chan "starting")
(chanl:send results-chan (funcall fun))))
(loop :repeat count
:collect (chanl:recv start-chan))
(format t "All started.")
(loop :repeat count
:collect (chanl:recv results-chan))))
在后台,chanl
使用一个简单的线程池。您可以看看它是如何做到的,它非常简洁易读。