对多线程映像最深刻的估计就是资源同步问题了,现在想想陈瑜老师的OS课上关于互斥锁什么的描述,基本上忘光了。废话不说,既然要做web相关的系统应用,总不能因为web的阻塞而一直停在那里不干活对吧,所以我觉得多线程跑起来应该还是有点必要的。我设置了四个线程:

QQ线程
这个线程的工作很简单,负责QQ登陆,接受QQ服务器的消息,并把消息塞到消息队列里去,当然也要负责另外一些诸如怎么保障持续在线,甚至下线了还能继续连接。

处理消息线程
这个线程的工作是依次处理消息队列里的消息,并根据不同的消息调用后台的AI来负责应答,我之前想过是不是要对每一个会话单独产生线程,这样可以保留上下文环境,不至于每次只能一问一答,但是好像复杂了些,以后再想好了。之后这个线程会把产生的应答塞到发送消息队列里去。另外,还会把每次处理的消息写进Log,方便之后查询。

发送消息线程
这个线程主要负责发送消息,以及在发送同时把发送消息写进对应的Log文件,这样每一个Log文件就相当于是QQ的聊天记录一样,方便以后的处理。

产生特定消息线程
这个线程使我们的系统更有定制性,并不局限于每次只有消息来临时才产生应答,我们可以在合适的时间,比如晚上10点,往发送消息队列里塞进一个晚安的消息,这样就可以主动的发送消息给特定的人。

说实话之前还没写过Python的多线程代码,趁昨晚学习了一下,好像不是很难,特别是我用了Python Queue,让整个多线程中最蛋疼的资源管理变得简单了很多,不需要自己写Lock,下面仅以产生特定消息线程为例给出源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# Generate special message
class generate_msg_thread(threading.Thread):
def __init__(self, send_queue, qq):
threading.Thread.__init__(self)
self.send_queue = send_queue
self.qq = qq

def run(self):
# Just a simple example, say goodnight to dear friends
# 这里还没有设置到10点再发晚安,因为等不到那个点啊,先写个简单的测试一下先
goodnight = True
while 1:
time.sleep(10)
try:
if goodnight and 'CPT' in self.qq.name2id:
self.send_queue.put((str(self.qq.name2id['CPT']), '晚安'))
goodnight = False
except Exception as e:
pass

if __name__ == "__main__":
gene = generate_msg_thread(send_msg_queue, qq)
# 让父线程结束的时候,子线程也退出,这样方便调试~不然每次都要通过kill来关闭不是么?
gene.setDaemon(True)
gene.start()

# 不要让父线程结束,不然子线程也结束了
while 1:
time.sleep(10)

OK,现在位置基本上整个框架算是粗糙的搭建完成了,剩下的工作才是真正的核心!下面要实现什么呢?还是先不要说,等写完了再说,不然说了没完成太丢脸了…