Python3并发编程之多线程

并发:假同时,一段时间内同时处理多个任务

并行:真同时,同时处理多个任务,必须多核,是并发的子集

threading.Thread(group=None, target=None, name=None, args=(), kwargs={}, *, daemon=None)

线程

import threading
def worker():
    print('work')
thread = threading.Thread(target=worker) # 创建线程对象,target参数是一个函数,这个函数即线程要执行的逻辑
thread.start() # start函数启动一个线程,当这个线程的逻辑执行,设计自动退出,自己退出。
import time
def worker(num):
    time.sleep(1)
    print('worker-{}'.format(num))
for z in range(5):
    t = threading.Thread(target=worker, args=(z, )) # 元组参数列表
    t.start()
    如何标识一个线程
threading.current_thread() # 返回当前线程
<<<_MainThread(MainThread, started 140428986173248)>
thread = threading.current_thread()
thread.name # 线程名,可重名
<<'MainThread'
thread.ident # 线程id
<<140428986173248
    logging
import logging
logging.warning('haha')
<<WARNING:root:haha
import importlib
importlib.reload(logging) # 重新引入,覆盖缓存
# import导入一次会在缓存中固定,,reload会从标准库中导入
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(levelname)s %(threadName)s %(message)s') # 配置logging
logging.warning('haha') # 替代print
<<2017-03-11 09:42:47,814 WARNING [MainThread haha]
    参数
# 通过args参数传递位置参数,通过kwargs传递关键字参数
def add(x, y):
    logging.info(x + y)
add(1, 2)
add(x=1, y=2)
threading.Thread(target=add, args=(1, 2)).start()
threading.Thread(target=add, kwargs={'x':1, 'y':2}).start()
threading.Thread(target=add, args=(1,), kwargs={'y':2}).start()
<<2017-03-11 09:45:23,651 INFO [Thread-18 3]
    线程名
threading.Thread(target=add, args=(1, 2), name='adc').start()
2017-03-11 09:47:55,442 INFO [adc 3]
# 通过name参数设置线程名字,日志可以带线程名
# 线程可以重名,唯一标识符是id,但是通常应该避免线程重名。通常线程名命名加前缀
    线程通信的必要
importlib.reload(logging)
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(levelname)s [%(threadName)s %(message)s]')
def ww(num):
    logging.info('ww-{}--'.format(num))
    time.sleep(1)
    logging.info('ww-{}'.format(num))
for i in range(5):
    t = threading.Thread(target=ww, args=(i, ), name='ww1')
    t.start()
for i in range(5):
    t = threading.Thread(target=ww, args=(i, ), name='ww2')
    t.start()
<<2017-03-11 10:24:58,067 INFO [ww1 ww-0--]
<<2017-03-11 10:24:58,071 INFO [ww1 ww-1--]
<<2017-03-11 10:24:58,074 INFO [ww1 ww-2--]
<<2017-03-11 10:24:58,076 INFO [ww1 ww-3--]
<<2017-03-11 10:24:58,078 INFO [ww1 ww-4--]
<<2017-03-11 10:24:58,081 INFO [ww2 ww-0--]
<<2017-03-11 10:24:58,084 INFO [ww2 ww-1--]
<<2017-03-11 10:24:58,086 INFO [ww2 ww-2--]
<<2017-03-11 10:24:58,105 INFO [ww2 ww-3--]
<<2017-03-11 10:24:58,121 INFO [ww2 ww-4--]
<<2017-03-11 10:24:59,073 INFO [ww1 ww-0]
<<2017-03-11 10:24:59,074 INFO [ww1 ww-1]
<<2017-03-11 10:24:59,077 INFO [ww1 ww-2]
<<2017-03-11 10:24:59,080 INFO [ww1 ww-3]
<<2017-03-11 10:24:59,082 INFO [ww1 ww-4]
<<2017-03-11 10:24:59,086 INFO [ww2 ww-0]
<<2017-03-11 10:24:59,087 INFO [ww2 ww-1]
<<2017-03-11 10:24:59,106 INFO [ww2 ww-2]
<<2017-03-11 10:24:59,122 INFO [ww2 ww-3]
<<2017-03-11 10:24:59,130 INFO [ww2 ww-4]
# 多线程自动并发,各线程调度顺序需要进程间通信来控制
    daemon
# 在pycharm中
import time
import logging
import threading

logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(levelname)s [%(threadName)s %(message)s]')
def worker1():
    logging.info('starting')
    time.sleep(20)
    logging.info('completed')
def worker2():
    logging.info('starting')
    time.sleep(3)
    logging.info('completed')
if __name__ == '__main__':
    logging.info('start1')
    t = threading.Thread(target=worker1, name='non-daemon')
    t.start()
    t = threading.Thread(target=worker2, daemon=True, name='daemon')
    t.start()
    logging.info('stop1')
<<2017-03-11 11:30:08,007 INFO [MainThread start1]
<<2017-03-11 11:30:08,026 INFO [non-daemon starting]
<<2017-03-11 11:30:08,044 INFO [daemon starting]
<<2017-03-11 11:30:08,045 INFO [MainThread stop1]
<<2017-03-11 11:30:11,048 INFO [daemon completed]
<<2017-03-11 11:30:28,040 INFO [non-daemon completed]
# daemon参数默认False
# daemon标记的子线程会随父线程退出而退出,可能执行完,可能未执行完
# none-daemon标记的子线程,主线程会等待其执行完再退出

依靠时间片解述:

    join
# join方法会阻塞,直到线程退出或者超时,timeout 是可选的,如果不设置timeout,会一直等待线程退出。不占用CPU时间
# 可用来强制等待deamon线程执行完成
t.join()
# 默认等待退出
t.join(timeout)
# 等待超时
    thread local
del(thread) # 删除对象
ctz = threading.local()
ctz.data = 5
data = 'abc'
def worker():
    logging.info(data)
    logging.info(ctz.data)
worker()
<<2017-03-11 11:19:16,158 INFO [MainThread abc]
<<2017-03-11 11:19:16,173 INFO [MainThread 5]
threading.Thread(target=worker).start()
<<2017-03-11 11:21:12,623 INFO [Thread-23 abc]
# threading.local()增加的属性只存在当前线程,只对当前线程可见
    定时器/延迟执行
def worker():
    logging.info('run')
t = threading.Timer(interval=5, function=worker) # 用function不是target
t.start() # 停顿5秒 执行,没有name
t.name
<<'Thread-28'
<<2017-03-11 11:37:50,080 INFO [Thread-28 run]
t.name = 'worker' # 这样设置name
t.start()
t.cancel() 
# 取消执行,线程结束。 在start后,在interval内,之间存在
threading.enumerate() # 查看当前所有线程

def worker():
    logging.info('starting')
    time.sleep(30)
    logging.info('completed')
t = threading.Timer(interval=0, function=worker)
t.start()
<<2017-03-11 11:45:50,224 INFO [Thread-32 starting]
t.cancel()
t.is_alive()
<<True
<<2017-03-11 11:46:20,248 INFO [Thread-32 completed]
# 当function参数指定函数开始执行的时候,cancel无效,无法取消

 

转载于:https://my.oschina.net/charlock/blog/856768

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值