python-thread

对CPU密集型代码(比如循环计算) - 多进程效率更高
对IO密集型代码(比如文件操作,网络爬虫) - 多线程效率更高。

th.setDaemon(True)守护线程

python中得thread的一些机制和C/C++不同:在C/C++中,主线程结束后,其子线程会默认被主线程kill掉。而在python中,主线程结束后,会默认等待子线程结束后,主线程才退出。

那么尴尬的问题就出现了,有一种情况,比如说在linux系统中存在脱离于终端的线程,即父进程在创建子进程之后先于子进程退出,会造成这个子进程变为“孤儿进程”

如果你忘记杀死子线程,那么好了,你杀主线程的时候其就会挂起等待直至子线程结束,所以为了避免这样的情况,python有两个函数管理线程:join和setDaemon

join:如在一个线程B中调用threada.join(),则threada结束后,线程B才会接着threada.join()往后运行。
setDaemon:主线程A启动了子线程B,调用b.setDaemaon(True),则主线程结束时,会把子线程B也杀死,与C/C++中得默认效果是一样的。

tkinter

tkinter 可以传入 控件对象到线程中,用于更新界面

self.frameOutput.pack(side=tk.TOP, fill=tk.BOTH, expand=1, pady=4)
self.frameReport.pack_forget()
thrd = threading.Thread(target=dbService.check_data,args=(self.textOutput,))
thrd.setDaemon(True) # 守护线程
thrd.start()

线程间通讯

Queue 对象已经包含了必要的锁,所以你可以通过它在多个线程间多安全地共享数据。

from queue import Queue
from threading import Thread

# A thread that produces data
def producer(out_q):
while True:
# Produce some data
...
out_q.put(data)

# A thread that consumes data
def consumer(in_q):
while True:
# Get some data
try:
it = in_q.get_nowait()
except queue.Empty as e1:
continue
if it is None:
break
# Process the data
...

# Create the shared queue and launch both threads
q = Queue()
t1 = Thread(target=consumer, args=(q,))
t2 = Thread(target=producer, args=(q,))
t1.setDaemon(True)
t1.start()
t2.setDaemon(True)
t2.start()

停止

使用类来实现

class CountdownTask:
def __init__(self):
self._running = True

def terminate(self):
self._running = False

def run(self, n):
while self._running and n > 0:
print('T-minus', n)
n -= 1
time.sleep(5)

c = CountdownTask()
t = Thread(target=c.run, args=(10,))
t.start()
c.terminate() # Signal termination
t.join() # Wait for actual termination (if needed)