8-3 如何线程间事件通知

Posted 石中玉smulngy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了8-3 如何线程间事件通知相关的知识,希望对你有一定的参考价值。

一、tar包打包

import tarfile
import os

def FunTarFile(tfname):
    tf = tarfile.open(tfname,\'w:gz\') #open打开一个tar包,‘w’打开模式为写 ‘:gz’压缩模式gzip

    for fname in os.listdir(\'.\'):     #遍历当前目录的文件
        if fname.endswith(\'.docx\'):
            tf.add(fname)             #将此文件加入tar包
            os.remove(fname)          #移除此文件

    tf.close()
    print (tf.members)                #打印tar包成员信息
    if not tf.members:              #判断tar包是否为空
        os.remove(tfname)           #如果tar包为空,删除此tar包

FunTarFile(\'DocxTar.tgz\')

输出结果:

[<TarInfo \'8-1 \\xc8\\xe7\\xba\\xce\\xca\\xb9\\xd3\\xc3\\xb6\\xe0\\xcf\\xdf\\xb3\\xcc - \\xb8\\xb1\\xb1\\xbe.docx\' at 0x27d0330>, <TarInfo \'8-2 \\xc8\\xe7\\xba\\xce\\xcf\\xdf\\xb3\\xcc\\xbc\\xe4\\xcd\\xa8\\xd0\\xc5 - \\xb8\\xb1\\xb1\\xbe.docx\' at 0x27d0370>, <TarInfo \'8-3 \\xc8\\xe7\\xba\\xce\\xcf\\xdf\\xb3\\xcc\\xbc\\xe4\\xca\\xc2\\xbc\\xfe\\xcd\\xa8\\xd6\\xaa - \\xb8\\xb1\\xb1\\xbe.docx\' at 0x2602d30>]

二、事件通知使用方法:

>>> from threading import Event,Thread
>>> 
>>> def f(e):
    print(\'f 0\')
    e.wait()            #事件等待,阻塞
    print(\'f 1\')

    
>>> e = Event()
>>> t = Thread(target=f, args=(e,))  #创建子线程,运行f函数
>>> t.start()         #子线程运行
f 0                 #子线程阻塞到事件等待中
>>> 
e.set()               #主线程里 事件发送
f 1                 #子线程继续执行
>>> 

此时再调用 wait()阻塞时,就不再起作用了,需要先调用e.clear()清除才能再使用wait()阻塞

 

# -*- coding: cp936 -*-

from threading import Thread,Event
from Queue import Queue
from time import sleep

"""
下载线程,下载后将下载号和数据写入队列
"""
class DownThread(Thread):
    def __init__(self,sid,queue):
        #Thread.__init__(self)
        super(DownThread,self).__init__()
        self.sid = sid
        self.queue = queue

    def downLoad(self,sid):
        print("Download (%d)..." %sid)
        sleep(2)

    def run(self):
        self.downLoad(self.sid)
        data = self.sid+100
        self.queue.put((self.sid,data))

"""
转换线程,从队列中读出数据进行文件转换,数换一定数量后发事件通知打包线程,此线程暂停
"""
class ConvelThread(Thread):
    def __init__(self,queue,tEvent,cEvent):
        #Thread.__init__(self)
        super(ConvelThread,self).__init__()
        self.queue = queue
        self.tEvent = tEvent
        self.cEvent = cEvent
        self.count = 0

    def convel(self,sid,data):
        print("Convel  (%d)-(%d)" %(sid ,data))

    def run(self):
        while(True):
            sid, data = self.queue.get() #元组解包的形式得到数据
            if(sid == -1):
                if self.count != 0:      #当退出时判断是否还需要打包的,
                    self.tEvent.set()   #如需要发送打包事件
                    self.cEvent.wait()  #并等待打包完再退出。
                break
            if(data):
                self.convel(sid,data)
                self.count += 1
                if self.count == 5:
                    self.tEvent.set()   #发送打包事件
                    self.cEvent.wait()  #等待转换事件
                    self.tEvent.clear() #清空打包事件
                    self.count = 0
                    

"""
打包线程,等到转换线程通知后,开始打包,打包完成后通知转换线程继续转换,此线程暂停打包
"""
class TarThread(Thread):
    def __init__(self,tEvent,cEvent):
        #Thread.__init__(self)
        super(TarThread,self).__init__()
        self.count = 0
        self.tEvent = tEvent
        self.cEvent = cEvent
        self.setDaemon(True)                #设置守护线程,当其他所有线程结束了,此线程也结束

    def FunTar(self,count):
        print (\'Tar count - %d\' %count)

    def run(self):
        while True:
            self.tEvent.wait()          #等特打包事件通知 
            self.count += 1
            self.FunTar(self.count)
            self.tEvent.clear()         #清空打包事件
            self.cEvent.set()           #发送转换事件
            

if __name__ == \'__main__\':
    q = Queue()
    tEvent = Event()
    cEvent = Event()

    dThreads = [DownThread(i,q) for i in xrange(1,13)]

    cThread = ConvelThread(q,tEvent,cEvent)
    tThread = TarThread(tEvent,cEvent)

    for t in dThreads:
        t.start()
        
    cThread.start()
    tThread.start()
    for t in dThreads:
        t.join()
        

    q.put((-1,None))

    cThread.join()
   # tThread.join()     #有此代码时,不打印下面的,因为主线程等待转换线程退出,转换线程是守护线程,需要所有线程都退出后,才能退出

print(\'MainThread\')

 

输出结果:

Download (1)...Download (4)...Download (2)...Download (5)...Download (3)...Download (6)...Download (7)...Download (8)...Download (9)...Download (10)...Download (11)...Download (12)...

Convel  (1)-(101)
Convel  (4)-(104)
Convel  (2)-(102)
Convel  (5)-(105)
Convel  (3)-(103)
Tar count - 1
Convel  (6)-(106)
Convel  (7)-(107)
Convel  (8)-(108)
Convel  (9)-(109)
Convel  (10)-(110)
Tar count - 2Convel  (11)-(111)

Convel  (12)-(112)
Tar count - 3MainThread

 

 

 

以上是关于8-3 如何线程间事件通知的主要内容,如果未能解决你的问题,请参考以下文章

JVM如何通知长时间运行的线程“停止”[重复]

将通知设置为在某个用户事件时触发

从活动中调用片段事件

转:Java并发编程之十二:线程间通信中notifyAll造成的早期通知问题(含代码)

notify,wait,synchronized实现线程间通知

Java并发编程之十二:线程间通信中notifyAll造成的早期通知问题(含代码)