Python-threading并发操作

本文详细介绍了Python的threading模块,包括Thread对象、当前线程获取、守护线程设置、线程列举、线程派生、定时器、线程间信号、锁的使用、再入锁、条件变量、信号量以及线程局部存储,是Python并发编程的重要参考资料。
摘要由CSDN通过智能技术生成

通过使用线程,程序可以在用一个进程空间并发地运行多个操作,threading模块建立在thread的底层特性基础之上,可以更容易地完成线程处理。


1. Thread对象(threading.Thread)

要使用Thread,最简单的方法是用一个目标函数实例化一个Thread对象,并调用start()让它开始工作。
import threading

def worker():
    print "Worker"
    return

threads = []
for i in range(5):
    t = threading.Thread(target = worker)
    threads.append(t)
    t.start()
当然,也可以向线程函数中添加参数,任何类型的对象都可以作为参数传递到线程中,下面的例子是传递了一个参数,线程打印出这个数:
import threading

def worker(num):
    print 'Worker: %s' % num
    return

threads = []
for i in range(5):
    t = threading.Thread(target=worker, args=(i,))
    threads.append(t)
    t.start()


2. 确定当前线程(threading.currentThread)

使用参数来标识或者命名线程很麻烦,也没有必要。每个Thread实例都有一个名称,它有一个默认值,可以在创建线程时改变。如果服务器进程由处理不同操作的多个服务器线程构成,在这样的服务器进程中,对线程命名就很有用。
import threading
import time

def worker():
    print threading.currentThread().getName(), ' Starting'
    time.sleep(2)
    print threading.currentThread().getName(),' Exiting'

def my_service():
    print threading.currentThread().getName(),' Starting'
    time.sleep(3)
    print threading.currentThread().getName(),' Exiting'

t = threading.Thread(name = 'my_service', target = my_service)  # or t.setName('my_service')
w = threading.Thread(name = 'worker', target = worker)
w2 = threading.Thread(target = worker)

w.start()
w2.start()
t.start()
从结果中可以看出,每一行都包含当前线程的名称,线程名称为“Thread-1"的行对应的未命名的线程为w2.:
worker  Starting
Thread-1  Starting
my_service  Starting
worker  Exiting
Thread-1  Exiting
my_service  Exiting

大多数程序不使用print来进行调试。logging模块支持将线程名嵌入到各个日志消息中(使用格式化代码%(threadName)s)。通过将线程名包含在日志消息中,就能跟踪这些消息的来源。
import threading
import logging
import time

logging.basicConfig(
        level = logging.DEBUG,
        format = '[%(levelname)s] (%(threadName)-10s)  %(message)s',
        )

def worker():
    logging.debug('Starting')
    time.sleep(2)
    logging.debug('Exiting')

def my_service():
    logging.debug('Starting')
    time.sleep(3)
    logging.debug('Exiting')

t = threading.Thread(name = 'my_service', target = my_service)
w = threading.Thread(name = 'worker', target = worker)
w2 = threading.Thread(target = worker)

w.start()
w2.start()
t.start()
执行结果为:
[DEBUG] (worker    )  Starting
[DEBUG] (Thread-1  )  Starting
[DEBUG] (my_service)  Starting
[DEBUG] (worker    )  Exiting
[DEBUG] (Thread-1  )  Exiting
[DEBUG] (my_service)  Exiting

3. 守护线程(setDaemon)

上面的实例中都隐含地等待所有线程完成工作后退出。程序有时会创建一个线程作为守护线程(daemon),这个线程在后台一直运行而不阻塞主程序退出。如果一个服务无法用一种容易地方法来中断线程,或者希望工程工作到一半时终止了而不损失或者破坏数据,对于这些服务,使用守护线程就很有用。要标志一个线程为守护线程,需要调用其setDaemon()方法并提供参数TRUE。默认情况下线程不作为守护线程。
import threading
import time
import logging

logging.basicConfig(level = logging.DEBUG,
        format = '(%(threadName)-10s) %(message)s',
        )

def daemon():
    logging.debug('Stating')
    time.sleep(3)
    logging.debug('Exiting')

d = threading.Thread(name = 'daemon', target = daemon)
d.setDaemon(True)

def non_daemon():
    logging.debug('Starting')
    logging.debug('Exiting')
t = threading.Thread(name = 'non-daemon', target = non_daemon)

d.start()
t.start()

#d.join(1)
#print 'd.isAlive()', d.isAlive()
#t.join()
输出结果为:
(daemon    ) Stating
(non-daemon) Starting
(non-daemon) Exiting
要等待一个守护进程结束工作,可使用join()方法,默认情况下jion会无限阻塞,也可以给jion传入参数,表示等待线程结束的时间(秒),即使在等待时间内线程没有结束,jion也会返回。将上面的程序最后三行解开,从下面结果中可以看出,由于传入参数小于守护进程睡眠时间,所以join()返回之后这个线程任然存活。
(daemon    ) Stating
(non-daemon) Starting
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值