python threading模块
1 # http://www.runoob.com/python3/python3-multithreading.html 2 # https://docs.python.org/3/library/threading.html 3 # http://yoyzhou.github.io/blog/2013/02/28/python-threads-synchronization-locks/ 4 # http://www.jb51.net/article/119414.htm 5 # http://blog.csdn.net/tomato__/article/details/46606045 6 # https://www.cnblogs.com/Ajen-lq/p/5325827.html 7 8 9 import threading # module 10 import socket 11 import random 12 import time 13 import queue 14 import requests 15 16 17 # ['get_ident', 1、返回线程号,一个数字 18 # 'active_count', 2、存活的线程数 19 # 'Condition', 3、条件锁 20 # 'current_thread', 4、返回当前线程的对象 21 # 'enumerate', 5、存活线程的列表 22 # 'main_thread', 6、返回主线程对象,python解释器启动的线程 23 # 'TIMEOUT_MAX', 24 # 'Event', 8、事件锁 25 # 'Lock', 9、互斥锁 26 # 'RLock', 10、重入锁,递归锁 27 # 'Semaphore', 11、信号量锁 28 # 'BoundedSemaphore', 12、有限信号量类 29 # 'Thread', 13、线程 30 # 'Barrier', 14、栅栏 31 # 'BrokenBarrierError', 32 # 'Timer', 16、定时任务 33 # 'ThreadError', 34 # 'setprofile', 35 # 'settrace', 36 # 'local', 20、 37 # 'stack_size'] 38 # Python线程同步机制: Locks, RLocks, Semaphores, Conditions, Events和Queues 39 40 41 # 1、get_ident 42 def foo(): 43 print('threading identify no: %s' % threading.get_ident()) 44 45 46 t1 = threading.Thread(target=foo) 47 t2 = threading.Thread(target=foo) 48 t3 = threading.Thread(target=foo) 49 t1.start() 50 t2.start() 51 t3.start() 52 t1.join() 53 t2.join() 54 t3.join() 55 56 57 # 2、active_count 58 def foo(): 59 time.sleep(1) 60 61 62 t1 = threading.Thread(target=foo) 63 t2 = threading.Thread(target=foo) 64 t3 = threading.Thread(target=foo) 65 t1.start() 66 print(threading.active_count()) # 2 67 t2.start() 68 print(threading.active_count()) # 3 69 t3.start() 70 print(threading.active_count()) # 4 71 t1.join() 72 t2.join() 73 t3.join() 74 75 76 # 3、Condition 一个线程等待特定条件,而另一个线程发出特定条件满足的信号 77 # class Condition(builtins.object) Class that implements a condition variable. 78 # A condition variable allows one or more threads to wait until they are notified by another thread. 79 # notify(self, n=1) Wake up one or more threads waiting on this condition, if any. 80 # notify_all(self) Wake up all threads waiting on this condition. 81 # wait(self, timeout=None) Wait until notified or until a timeout occurs. 82 # wait_for(self, predicate, timeout=None) Wait until a condition evaluates to True. 83 # wait()方法释放锁,然后阻塞直到另一个线程调用notify()或者notify_all()唤醒它。唤醒后,wait()重新获取锁并返回。它也可以指定一个超时时间。 84 # notify()方法唤醒等待线程中的一个;notify_all()方法唤醒所有等待线程。 85 # 注意:notify()和notify_all()方法不释放锁;这意味着唤醒的线程或者线程组将不会从wait()调用中立即返回。 86 # 一个条件变量允许一个或多个线程等待,直到他们被另一个线程通知。 87 # wait()一旦唤醒或者超时,它重新请求锁并返回。 88 89 90 class Producer(threading.Thread): 91 92 def __init__(self, integers, condition): 93 threading.Thread.__init__(self) 94 self.integers = integers 95 self.condition = condition 96 97 def run(self): 98 while True: 99 integer = random.randint(0, 256) 100 with self.condition: # 获取条件锁 101 print('condition acquired by %s' % self.name) 102 self.integers.append(integer) 103 print('%d appended to list by %s' % (integer, self.name)) 104 print('condition notified by %s' % self.name) 105 self.condition.notify() # 唤醒消费者线程 106 print('condition released by %s' % self.name) 107 time.sleep(1) # 暂停1秒钟 108 109 110 class Consumer(threading.Thread): 111 def __init__(self, integers, condition): 112 threading.Thread.__init__(self) 113 self.integers = integers 114 self.condition = condition 115 116 def run(self): 117 while True: 118 with self.condition: # 获取条件锁 119 print('condition acquired by %s' % self.name) 120 while True: 121 if self.integers: # 判断是否有整数 122 integer = self.integers.pop() 123 print('%d popped from list by %s' % (integer, self.name)) 124 break 125 print('condition wait by %s' % self.name) 126 self.condition.wait() # 等待商品,并且释放资源让生产者执行 127 print('condition released by %s' % self.name) 128 129 130 def main(): 131 integers = [] 132 condition = threading.Condition() 133 t1 = Producer(integers, condition) 134 t2 = Consumer(integers, condition) 135 t1.start() 136 t2.start() 137 t1.join() 138 t2.join() 139 140 141 main() 142 143 144 # 4、current_thread 145 def foo(): 146 print(threading.current_thread()) 147 148 149 t1 = threading.Thread(target=foo) 150 t1.start() 151 t1.join() 152 153 154 # 5、enumerate 155 def foo(): 156 time.sleep(1) 157 158 159 t1 = threading.Thread(target=foo) 160 t2 = threading.Thread(target=foo) 161 t3 = threading.Thread(target=foo) 162 t1.start() 163 t2.start() 164 t3.start() 165 print(threading.enumerate()) 166 t1.join() 167 t2.join() 168 t3.join() 169 170 171 # 6、main_thread 172 def foo(): 173 time.sleep(1) 174 175 176 t1 = threading.Thread(target=foo) 177 t1.start() 178 print(threading.main_thread()) 179 t1.join() 180 181 182 # 8、Event 事件锁 一个线程发送/传递事件,另外的线程(多线程)等待事件的触发。 183 # class Event(builtins.object) Class implementing event objects. 184 # Events manage a flag that can be set to true with the set() method and reset to false with the clear() method. 185 # The wait() method blocks until the flag is true. The flag is initially false. 186 # set(self) Set the internal flag to true. All threads waiting for it to become true are awakened. 187 # Threads that call wait() once the flag is true will not block at all. 188 # clear(self) Reset the internal flag to false. 189 # is_set(self) Return true if and only if the internal flag is true. 190 # wait(self, timeout=None) Block until the internal flag is true. 191 # isSet = is_set(self) 192 193 194 class Producer(threading.Thread): 195 def __init__(self, integers, event): 196 threading.Thread.__init__(self) 197 self.integers = integers 198 self.event = event 199 200 def run(self): 201 while True: 202 integer = random.randint(0, 256) 203 self.integers.append(integer) 204 print('%d appended to list by %s' % (integer, self.name)) 205 print('event set by %s' % self.name) 206 self.event.set() # 设置事件 207 self.event.clear() # 发送事件 208 print('event cleared by %s' % self.name) 209 time.sleep(1) 210 211 212 class Consumer(threading.Thread): 213 def __init__(self, integers, event): 214 threading.Thread.__init__(self) 215 self.integers = integers 216 self.event = event 217 218 def run(self): 219 while True: 220 self.event.wait() # 等待事件被触发 221 # self.event.wait(timeout=2) # 等待事件被触发,超时之后,不再阻塞,继续执行 222 try: 223 integer = self.integers.pop() 224 print('%d popped from list by %s' % (integer, self.name)) 225 except IndexError: 226 # catch pop on empty list 227 time.sleep(1) 228 229 230 def main(): 231 integers = [] 232 event = threading.Event() 233 t1 = Producer(integers, event) 234 t2 = Consumer(integers, event) 235 t1.start() 236 t2.start() 237 t1.join() 238 t2.join() 239 240 241 main() 242 243 244 # 9、Lock互斥锁 245 # class lock(builtins.object) A lock object is a synchronization primitive. To create a lock, call threading.Lock(). 246 # acquire() -- lock the lock, possibly blocking until it can be obtained 247 # release() -- unlock of the lock 248 # locked() -- test whether the lock is currently locked 249 # acquire(...) acquire_lock(...) acquire(blocking=True, timeout=-1) 250 # locked(...) locked_lock(...) locked() -> bool 251 # release(...) release_lock(...) release() 252 253 254 class FetchUrls(threading.Thread): 255 def __init__(self, urls, output, lock): 256 threading.Thread.__init__(self) 257 self.urls = urls 258 self.output = output 259 self.lock = lock 260 261 def run(self): 262 while self.urls: 263 url = self.urls.pop() 264 req = requests.get(url) 265 with self.lock: 266 self.output.write(req.content) 267 print('write done by %s' % self.name) 268 print('URL %s fetched by %s' % (url, self.name)) 269 270 271 def main(): 272 lock = threading.Lock() 273 urls1 = ['http://www.baidu.com', 'http://www.sina.com'] 274 urls2 = ['http://www.sohu.com', 'http://www.youku.com'] 275 f = open('output.txt', 'wb+') 276 t1 = FetchUrls(urls1, f, lock) 277 t2 = FetchUrls(urls2, f, lock) 278 t1.start() 279 t2.start() 280 t1.join() 281 t2.join() 282 f.close() 283 284 285 main() 286 287 288 # 10、RLock可重入锁 289 # RLock是可重入锁(reentrant lock),acquire()能够不被阻塞的被同一个线程调用多次。要注意的是release()需要调用与acquire()相同的次数才能释放锁。 290 291 292 # 11、Semaphore信号量锁 293 # 信号量同步基于内部计数器,每调用一次acquire(),计数器减1;每调用一次release(),计数器加1.当计数器为0时,acquire()调用被阻塞。 294 # class Semaphore(builtins.object) This class implements semaphore objects. 295 # Semaphores manage a counter representing the number of release() calls minus the number of acquire() calls, plus an initial value. 296 # The acquire() method blocks if necessary until it can return without making the counter negative. 297 # If not given, value defaults to 1. 298 # acquire(self, blocking=True, timeout=None) Acquire a semaphore, decrementing the internal counter by one. 超时或者不阻塞返回false 299 # release(self) Release a semaphore, incrementing the internal counter by one. 300 301 302 class MyThread(threading.Thread): 303 def __init__(self, semaphore, list_): 304 threading.Thread.__init__(self) 305 self.semaphore = semaphore 306 self.list_ = list_ 307 308 def run(self): 309 with self.semaphore: 310 self.list_.append(2) 311 312 313 def main(): 314 list_ = [1, 2, 3] 315 semaphore = threading.Semaphore(2) # 允许同时2个线程访问共享资源,默认是1 316 t1 = MyThread(semaphore, list_) 317 t2 = MyThread(semaphore, list_) 318 t3 = MyThread(semaphore, list_) 319 t1.start() 320 t2.start() 321 t3.start() 322 t1.join() 323 t2.join() 324 t3.join() 325 print(list_) 326 327 328 main() 329 330 331 # 12、BoundedSemaphore有限信号量类 332 # “有限”(bounded)信号量类,可以确保release()方法的调用次数不能超过给定的初始信号量数值(value参数) 333 # 重写release方法 334 # If the number of releases exceeds the number of acquires, raise a ValueError. 335 336 337 # 13、Thread 338 # class Thread(builtins.object) A class that represents a thread of control. 339 # This class can be safely subclassed in a limited fashion. There are two ways to specify the activity: 340 # by passing a callable object to the constructor, or by overriding the run() method in a subclass. 341 # __init__(self, group=None, target=None, name=None, args=(), kwargs=None, *, daemon=None) 342 # group 为将来线程组扩展留的 343 # daemon 默认非守护线程 344 # getName(self) 方法 345 # isDaemon(self) 方法 346 # is_alive(self) 是否存活,run开始之后到run结束之前是True 347 # join(self, timeout=None) Wait until the thread terminates. 348 # run(self) Method representing the thread's activity. 349 # setDaemon(self, daemonic) 350 # setName(self, name) 351 # start(self) 352 # daemon 属性 353 # ident 属性 354 # name 属性 355 356 # 无join,无daemon 357 def foo(): 358 time.sleep(3) 359 360 361 t1 = threading.Thread(target=foo) 362 t1.start() 363 print('main thread go on') # 最后再等待线程,释放线程的资源,这里阻塞 364 365 366 # 有join 367 def foo(): 368 time.sleep(3) 369 370 371 t1 = threading.Thread(target=foo) 372 t1.start() 373 t1.join() # 等待线程结束,抓线程再继承执行,这里阻塞 374 print('main thread not go on') 375 376 377 # 有daemon 378 def foo(): 379 while True: 380 print('abc') 381 382 383 t1 = threading.Thread(target=foo) 384 t1.setDaemon(True) 385 t1.start() 386 print('main thread go on') # 主线程结束,要求子线程同时也结束,这里不阻塞了 387 388 389 # 14、Barrier 390 # class Barrier(builtins.object) Implements a Barrier. Useful for synchronizing a fixed number 391 # of threads at known synchronization points. 392 # Threads block on 'wait()' and are simultaneously once they have all made that call. 393 # __init__(self, parties, action=None, timeout=None) 394 # abort(self) Place the barrier into a 'broken' state. 方法,终止栅栏,wait会抛出异常 395 # reset(self) Reset the barrier to the initial state. 方法,恢复栅栏 396 # wait(self, timeout=None) Wait for the barrier. 方法,等待数量达到parties,一起通过栅栏 397 # broken Return True if the barrier is in a broken state. 属性,检查栅栏的状态,True是坏 398 # n_waiting Return the number of threads currently waiting at the barrier. 属性,正在wait的数量 399 # parties Return the number of threads required to trip the barrier. 属性,parties的数量 400 401 402 def server(b): 403 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 404 s.bind(("192.168.99.156", 5003)) 405 s.listen(5) 406 407 while True: 408 # print(b.broken) # False 409 # b.abort() 410 # print(b.broken) # True 411 # b.reset() 412 413 b.wait() 414 print(threading.get_ident()) 415 new_socket, client_addr = s.accept() 416 new_socket.sendall(bytes("Hello world", encoding="utf-8")) 417 new_socket.close() 418 time.sleep(3) 419 420 421 def client(b): 422 while True: 423 b.wait() # 超时 raise BrokenBarrierError 424 print(threading.get_ident()) 425 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 426 s.connect(("192.168.99.156", 5003)) 427 ret = str(s.recv(1024), encoding="utf-8") 428 print(ret) 429 time.sleep(0.1) 430 431 432 def callback(): 433 print('Barrier') 434 435 436 def main(): 437 b = threading.Barrier(2, action=callback, timeout=5) # 超时 raise BrokenBarrierError, 通过一次栅栏调用一次action 438 t1 = threading.Thread(target=server, args=(b, )) 439 t2 = threading.Thread(target=client, args=(b, )) 440 t1.start() 441 t2.start() 442 t1.join() 443 t2.join() 444 445 446 main() 447 448 449 # 16、Timer定时任务 450 # class Timer(Thread) Call a function after a specified number of seconds。 451 # __init__(self, interval, function, args=None, kwargs=None) 继承Thread 452 # 新增方法:cancel(self) 453 # 重写方法:run(self) 454 # 其他方法同Thread 455 456 457 def func(): 458 print('abc') 459 460 461 def main(): 462 t = threading.Timer(2, func) 463 t.start() 464 465 466 main() 467 468 469 # 20、local 470 localVal = threading.local() 471 localVal.val = "Main-Thread" # 每个线程单独创建内存空间来存储 472 a = 10 473 474 475 def print_student(): 476 global a 477 print('%s (in %s)' % (localVal.val, threading.current_thread().name)) 478 a += 100 # 操作的是主线程的变量 479 480 481 def print_thread(name): 482 localVal.val = name # 每个线程单独创建内存空间来存储 483 print_student() 484 485 486 def main(): 487 t1 = threading.Thread(target=print_thread, args=('One',), name='Thread-A') 488 t2 = threading.Thread(target=print_thread, args=('Two',), name='Thread-B') 489 t1.start() 490 t2.start() 491 t1.join() 492 t2.join() 493 print(localVal.val) 494 print(a) 495 496 497 main() 498 499 500 # 21、使用队列同步线程间共享资源 501 # 队列 Queue 502 class Producer(threading.Thread): 503 def __init__(self, q): 504 threading.Thread.__init__(self) 505 self.queue_ = q 506 507 def run(self): 508 while True: 509 integer = random.randint(0, 256) 510 self.queue_.put(integer) # 将生成的整数添加到队列 511 print('%d put to queue by %s' % (integer, self.name)) 512 time.sleep(1) 513 514 515 class Consumer(threading.Thread): 516 def __init__(self, q): 517 threading.Thread.__init__(self) 518 self.queue_ = q 519 520 def run(self): 521 while True: 522 integer = self.queue_.get() 523 print('%d popped from list by %s' % (integer, self.name)) 524 self.queue_.task_done() 525 526 527 def main(): 528 q = queue.Queue(20) 529 t1 = Producer(q) 530 t2 = Consumer(q) 531 t1.start() 532 t2.start() 533 t1.join() 534 t2.join() 535 536 537 main()