A thread
is a flow of control that shares global state with other threads; all threads appear to execute simultaneously.
A process
is an instance of a running program.
创建线程的两种方法
- 继承
Thread
类, 重写run()
方法, 而不是start()
- 创建
threading.Thread
对象,初始化函数__init__()
中可将调用对象作为参数传入
The thread
Module
1 2 3 | L.acquire(wait=True) # When wait is True, acquire locks L. L.locked( ) # Returns True if L is locked; otherwise, False. L.release( ) # Unlocks L, which must be locked. |
The Queue
Module
The Queue module supplies first-in, first-out (FIFO) queues that support multithread access, with one main class and two exception classes.
1 2 3 4 5 6 7 8 | class Queue(maxsize=0)
q.empty()
q.get(False)
q.full()
q.put(x,False)
q.get(block=True,timeout=None)
q.put(item,block=True,timeout=None)
q.qsize( )
|
“It’s easier to ask forgiveness than permission” (*EAFP) idiom vs
“look before you leap” (LBYL) idiom
1 2 3 4 | try: x=q.get_nowait() except Queue.Empty: print "no work to perform" |
Customizing Class Queue by Subclassing
You may customize Queue.Queue
by subclassing, and you need to override some or all of the hook methods that Queue.Queue provides for the purpose: _qsize
,_empty
, _full
, _put
, and _get
.
1 2 3 | import Queue class LIFOQueue(Queue.Queue): def _get(self): return self.queue.pop() |
The threading Module 推荐
threading
provides numerous classes for dealing with threads, including Thread, Condition, Event, RLock, and Semaphore.
1 2 3 4 5 6 7 8 9 10 | currentThread( ) class Thread(name=None,target=None,args=(),kwargs={ }) t.getName() t.setName(name) t.isAlive( ) t.isDaemon() t.setDaemon(daemonic) t.join(timeout=None) t.run( ) t.start( ) |
Ex1
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 30 31 32 | import threading, time, sys class test(threading.Thread): def __init__(self, name, delay): threading.Thread.__init__(self) self.name = name self.delay = delay def run(self): print "%s delay for %s" % (self.name, self.delay) time.sleep(self.delay) c = 0 while Ture: print "This is thread %s on line %s" % (self.name, c) c += 1 if c == 3 print "End of thread %s" % self.name break def main(): t1 = test('Thread 1', 1) t2 = test('Thread 2', 2) t1.start() print "Wait t1 to end" t1.join() print "End of t1" t2.start() print "Wait t2 to end" t2.join() print "End of t2" print "End of main" |
Thread Synchronization Objects
Timeout parameters
Lock and RLock objects
Condition objects
1 2 3 4 5 6 | class Condition(lock=None)
c.acquire(wait=1)
c.release( )
c.notify( )
c.notifyAll( )
c.wait(timeout=None)
|
In typical use, a Condition object c
regulates access to some global state s
that is shared between threads. When a thread needs to wait for s
to change, the thread loops as follows:
1 2 3 4 5 | c.acquire( ) while not is_ok_state(s): c.wait( ) do_some_work_using_state(s) c.release( ) |
Meanwhile, each thread that modifies s
calls notify
(or notifyAll
if it needs to wake up all waiting threads, not just one) each time s
changes:
1 2 3 4 | c.acquire( ) do_something_that_modifies_state(s) c.notify() # or, c.notifyAll() c.release( ) |
Event objects
Event objects let any number of threads suspend and wait. All threads waiting on Event object e become ready when any other thread calls e.set( )
.
1 2 3 4 5 6 | class Event() e.clear( ) # Sets e’s flag to False. e.isSet( ) # Returns the value of e’s flag, True or False. e.set( ) # Sets e’s flag to True. e.wait(timeout=None) # If e’s flag is True, wait returns immediately. # Otherwise, wait suspends the calling thread until some other thread calls set. |
Semaphore objects
Semaphores
(also known as counting semaphores) are a generalization of locks. The state of a Lock can be seen as True
or False
; the state of a Semaphore s
is a number between 0
and somen
set when s
is created.
1 2 3 | class Semaphore(n=1)
s.acquire(wait=True)
s.release( )
|
Thread Local Storage
Module threading
supplies a class local
, which threads can use to obtain thread-local storage (TLS), also known as per-thread data. An instance L of local has arbitrary named attributes that you can set and get, and stores them in a dictionary L.__dict__
that you can also access. L is fully thread-safe, meaning there is no problem if multiple threads simultaneously set and get attributes on L.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | import threading L = threading.local() print 'in main thread, setting zop to 42' L.zop = 42 def targ(): print 'in subthread, setting zop to 23' L.zop = 23 print 'in subthread, zop is now', L.zop t = threading.Thread(target=targ) t.start( ) t.join( ) print 'in main thread, zop is now', L.zop |
Ex2
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 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | import os, Queue, threading, urllib2 class DownLoadThread(threading.Thread): """docstring for DownLoadThread""" def __init__(self, queue): #super(DownLoadThread, self).__init__() threading.Thread.__init__(self) self.queue = queue def run(self): while True: url = self.queue.get() # 从队列中取出一个url元素 print self.name + " begin downloading " + url + ' ...' self.download_file(url) self.queue.task_done() print self.name + " finished downloading " + url + ' !!!' def download_file(self, url): urlhander = urllib2.urlopen(url) fname = os.path.basename(url) + ".html" with open(fname, "wb") as f: chunk = urlhander.read(1024) if not chunk: break f.write(chunk) if __name__ == '__main__': urls = ["http://weibo.com/buttonwood", "http://www.douban.com/people/buttonwood/", "http://buttonwood.github.io" ] queue = Queue.Queue() # queue 队列本身能够保证线程安全,不需要额外的同步机制 # creat a thread pool and give them a queue for x in xrange(1,5): t = DownLoadThread(queue) # 5 thread for doanloading t.setDaemon(True) t.start() # give the queue some data for y in urls: queue.put(url) # wait for the queue to finish queue.join() |