@主要模块:thread模块,time模块
---模块函数:start_new_thread(func,args),allocate_lock(),exit。
锁对象有三个方法acquire(),locked(),release()。下面是如何生成锁对象:
---thread.allocate_lock() 生成锁对象,注意锁对象和线程是两个完全不同的概念
lock.acquire() 加锁,加锁后,线程就可以使用锁对象了
lock.release() 线程调度释放锁对象
---acquire负责加锁,release负责解锁。
如果锁定了,lock.locked()的状态为true,如果解锁了lock.locked()就是false
---一个使用案例:
上边代码中,首先声明一个播放视频函数(playVideo),下边声明一个锁对象,加锁。
下边声明两个新的线程,一个播放图片,播放30次,一个播放声音,播放30次。两个线程都上了锁。
当两者循环完以后,锁对象就会解锁l.release() ,lock.locked()状态就会变成false,就会退出循环。
1,什么是单线程?(一个时间点只能做一件事。)
在好些年前的MS-DOS时代,操作系统处理问题都是单任务的,我想做听音乐和看电影两件事儿,那么一定要先排一下顺序。
(好吧!我们不纠结在DOS时代是否有听音乐和看影的应用。^_^)
from time importctime,sleepdefmusic():for i in range(2):print "I was listening to music. %s" %ctime()
sleep(1)defmove():for i in range(2):print "I was at the movies! %s" %ctime()
sleep(5)if __name__ == '__main__':
music()
move()print "all over %s" %ctime()
我们先听了一首音乐,通过for循环来控制音乐的播放了两次,每首音乐播放需要1秒钟,sleep()来控制音乐播放的时长。接着我们又看了一场电影,每一场电影需要5秒钟,因为太好看了,所以我也通过for循环看两遍。在整个休闲娱乐活动结束后,我看了一下当前时间,差不多该睡觉了。
运行结果:
>>=========================== RESTART ================================
>>>I was listening to music. Thu Apr17 10:47:08 2014I was listening to music. Thu Apr17 10:47:09 2014I was at the movies! Thu Apr17 10:47:10 2014I was at the movies! Thu Apr17 10:47:15 2014all over Thu Apr17 10:47:20 2014
2,什么是多线程?同时做多件事情,例如同时执行多个方法。(@注意thread和threading用法是不同的?下边案例用的是threading方法)
科技在发展,时代在进步,我们的CPU也越来越快,CPU抱怨,P大点事儿占了我一定的时间,其实我同时干多个活都没问题的;于是,操作系统就进入了多任务时代。我们听着音乐玩着其他程序不在是梦想。
python提供了两个模块来实现多线程thread和threading ,thread 有一些缺点,在threading 得到了弥补,为了不浪费你和时间,所以我们直接学习threading 就可以了。
---threading模块建立在thread模块之上,可以更容易地管理多个执行线程。通过使用线程,程序可以在同一个进程空间并发地运行多个操作。threading模块建立在thread的底层特性基础之上,可以更容易地完成线程处理。
(1),第一个简单的实例
import threading
def worker(num):
print 'worker:%s' %num
return
threads=[]
for i in range(5):
t=threading.Thread(target=worker, args=(i, )) //任何类型的对象,都可以作为参数传递到线程。联系C#中的多线程一起记忆
threads.append(t)
t.start()
---输出5行
worker:0
worker:1
worker:2
worker:3
worker:4
(2),确定当前线程
使用参数来标识或命名线程很麻烦,也没有必要。每个Thread实例都有一个名称,它有一个默认值,可以在创建线程时改变。如果服务器进程由处理不同操作的多个服务线程构成,在这样的服务器进程中,对线程命名很有用。
print threading.currentThread().getName() //这段代码就能获取当前线程名,例如在上边worker方法中,加入这段代码,会输出Thread-5类似的线程名。
print threading.currentThread().getName(), num //这后面可以加上参数,就会输出Thread-1 0
print threading.currentThread().getName(), 'starting' //后面可以加上字符串,就会输出Thread-1 starting
(3),守护和非守护线程(守护线程的作用就是用一种容易的方法来中断线程!!!,具体用法,视情况而定。)
---在Java中也有两类线程:User Thread(用户线程)、Daemon Thread(守护线程)
守护线程的概念有点不同于Linux环境下的概念,可能是我没理解,但是这个概念和Java里的守护线程一样:
守护线程在主线程退出后也会随着退出,非守护线程(普通线程)则不会。什么意思呢?看下边:
* 对于普通线程,如果线程的任务没有结束,主线程不会退出,整个程序也不会退出(程序会被无限挂起);
* 对于守护线程,即使线程任务还没有结束,如果主线程退出该线程也会退出;
*守护线程作用:如果一个服务无法用一种容易的方法来中断线程,或者希望线程工作到一半时中止而不损失或破坏数据,对于这些服务,使用守护线程就很有用。要标志一个线程为守护线程,需要调用其setDaemon()放法并提供参数True。
---默认情况下线程不是守护线程。
* 实例如下:
#coding=utf8
import threading
import time
import logging
logging.basicConfig(level=logging.DEBUG, format='(%(threadName)-10s %(message)s', )
def daemon():
logging.debug('Starting')
time.sleep(2)
logging.debug('Exiting')
#这个函数执行线程,设置为守护线程以后,这里就不会再输出Exiting。因为在守护线程从其2秒的睡眠时间唤醒之前,所有非守护线程(包括主线程)已经退出。
#主线程退出后,守护线程也会退出,所以上边不会输出Exiting。
#(对于守护线程,即使线程任务还没有结束,如果主线程退出该线程也会退出;)
d=threading.Thread(name='daemon', target=daemon)
d.setDaemon(True) #如果这里注释掉,程序执行时,就会停顿2秒,输出Exiting。(为什么?因为对于普通线程,如果线程的任务没有结束,主线程不会退出,整个程序也不会退出;)
def non_daemon():
logging.debug('Starting')
logging.debug('Exiting')
t=threading.Thread(name='non-daemon', target=non_daemon)
d.start()
t.start()
* 要等待一个守护线程完成工作,需要使用join()方法。(join的作用:即使主线程退出,守护线程的任务没有结束,守护线程也不退出。)
1),在上边代码的最后加上如下代码:
d.join()
t.join()
使用join()等待守护线程退出,这意味着它就会输出"Exiting"消息。加了join以后,守护线程等于变成了普通线程了。
(daemon Starting
(non-daemon Starting
(non-daemon Exiting
(daemon Exiting
2),默认情况下,join()会无限阻塞。还可以传入一个浮点数值,表示等待线程变为不活动所需的时间(秒数)。即使线程在这个时间段内未完成,join()也会返回。
d.join(1)
print 'd.isAlive()',d.isAlive() //用isAlive()方法判断线程是否活动,true表示活动--存活,false表示不活动--中断,不存活。
t.join()
time.sleep(3) //如果不加下边三行代码,就不会输出(daemon )Exiting,守护线程会随主线程的退出而退出
print d.isAlive()
print t.isAlive()
由于传入的超时时间小于守护线程睡眠的时间,所以join()返回之后这个线程扔'存活'。在上面代码中,守护线程设置睡眠2秒(time.sleep(2)),上边,我们设置time.sleep(3),延长主线程退出时间,所以下边(daemon )Exiting依然会输出。输出所有后,两个线程的状态都是False(中断)。
(daemon ) Exiting
False
False