多线程
线程拥有自己独立的栈和共享的堆,共享堆,不共享栈,线程亦由操作系统调度(标准线程是的)。
threading
启动一个线程就是把一个函数传入并创建threading.Thread( )实例,然后调用start( )开始执行:
实例:
import threading #导入线程模块
import time
#线程函数
def foo(num):
print('我的进程名字为:'+threading.current_thread().name)
time.sleep(2)
print(num)
#创建进程 #callback:回调函数 一般用来接收子进程运行函数的返回值
t1 = threading.Thread(target=foo,args=(1,),callback=func)
t2 = threading.Thread(target=foo,args=(2,))
#启动线程
t1.start()
t2.start()
#获取线程运行状态 True为运行 False为未运行
print(t1.is_alive())
print(t2.is_alive())
#等待所有线程运行完毕在继续往下执行
t1.join()
t2.join()
执行结果为:
我的进程名字为:Thread-1
我的进程名字为:Thread-2
True #运行状态
True #运行状态
1 #第一个线程打印
2 #第二个线程打印
- threading.current_thread( ) 它返回当前线程的实例
- join( )在子线程执行完成之前,这个子线程的父线程将一直被阻塞。就是说,当调用join()的子进程没有结束之前,主进程不会往下执行。对其它子进程没有影响。
- is_alive() 获取线程的运行状态
守护进程setDaemon(True)
将线程声明为守护线程,必须在start() 方法调用之前设置, 如果不设置为守护线程程序会被无限挂起。这个方法基本和join是相反的。当我们 在程序运行中,执行一个主线程,如果主线程又创建一个子线程,主线程和子线程 就兵分两路,分别运行,那么当主线程完成想退出时,会检验子线程是否完成。如 果子线程未完成,则主线程会等待子线程完成后再退出。但是有时候我们需要的是 只要主线程完成了,不管子线程是否完成,都要和主线程一起退出,这时就可以用setDaemon方法。
实例:
import threading
from time import ctime,sleep
import time
def music(func):
for i in range(2):
print ("Begin listening to %s. %s" %(func,ctime()))
sleep(4)
print("end listening %s"%ctime())
def move(func):
for i in range(2):
print ("Begin watching at the %s! %s" %(func,ctime()))
sleep(5)
print('end watching %s'%ctime())
threads = []
t1 = threading.Thread(target=music,args=('七里香',))
threads.append(t1)
t2 = threading.Thread(target=move,args=('阿甘正传',))
threads.append(t2)
if __name__ == '__main__':
for t in threads:
t.setDaemon(True)
t.start()
print ("all over %s" %ctime())
执行结果为:
Begin listening to 七里香. Thu Sep 29 15:45:32 2016 #t1和t2启动,分别打印一次后sleep,主进程继续
Begin watching at the 阿甘正传! Thu Sep 29 15:45:32 2016
all over Thu Sep 29 15:45:32 2016 #主进程结束,程序结束
Lock互斥锁
多线程和多进程最大的不同在于,多进程中,同一个变量,各自有一份拷贝存在于每个进程中,互不影响,而多线程中,所有变量都由所有线程共享,所以,任何一个变量都可以被任何一个线程修改,因此,线程之间共享数据最大的危险在于多个线程同时改一个变量,把内容给改乱了。
实例:
import threading
num = 0
def add():
global num
for i in range(1000000):
num += 1
t1 = threading.Thread(target=add)
t2 = threading.Thread(target=add)
t1.start()
t2.start()
t1.join()
t2.join()
print(num)
运行结果为:
1183554
为什么会出现这样的问题呢 上面已经说过了,线程间任何一个变量都可以被任何一个线程修改,因此,线程之间共享数据最大的危险在于多个线程同时改一个变量,把内容给改乱了。这种情况要使用lock (互斥锁)
实例:
import threading
num = 0
def add():
global num
for i in range(1000000):
lock.acquire()#上锁
num += 1
lock.release()#解锁
#也可以使用with方法效果相同
# with lock:
# num += 1
t1 = threading.Thread(target=add)
t2 = threading.Thread(target=add)
#创建互斥锁 只能有一个进程同时访问
lock = threading.Lock()
t1.start()
t2.start()
t1.join()
t2.join()
print(num)
运行结果为:
2000000
信号量
信号量是允许同一时间同时几个线程访问共享变量
import threading,time
def foo(i):
# 上锁
sem.acquire()
time.sleep(1)
print(i)
# 解锁
sem.release()
# 锁 --- 信号量
sem = threading.BoundedSemaphore(3)
for i in range(10):
t = threading.Thread(target=foo,args=(i,))
t.start()
自己体验执行结果会更容易理解信号量
Event(事件)
小伙伴a,b,c围着吃火锅,当菜上齐了,请客的主人说:开吃!,于是小伙伴一起动筷子,这种场景如何实现?
Event(事件):事件处理的机制:全局定义了一个内置标志Flag,如果Flag值为 False,那么当程序执行 event.wait方法时就会阻塞,如果Flag值为True,那么event.wait 方法时便不再阻塞。Event没有锁,无法使线程进入同步阻塞状态。
set(): 将标志设为True,并通知所有处于等待阻塞状态的线程恢复运行状态。
clear(): 将标志设为False。
wait(timeout): 如果标志为True将立即返回,否则阻塞线程至等待阻塞状态,等待其他线程调用set()。
isSet(): 获取内置标志状态,返回True或False。
import threading
import time
event = threading.Event()
def chihuoguo(name):
# 等待事件,进入等待阻塞状态
print '%s 已经启动' % threading.currentThread().getName()
print '小伙伴 %s 已经进入就餐状态!'%name
time.sleep(1)
event.wait()
# 收到事件后进入运行状态
print '%s 收到通知了.' % threading.currentThread().getName()
print '小伙伴 %s 开始吃咯!'%name
# 设置线程组
threads = []
# 创建新线程
thread1 = threading.Thread(target=chihuoguo, args=("a", ))
thread2 = threading.Thread(target=chihuoguo, args=("b", ))
# 添加到线程组
threads.append(thread1)
threads.append(thread2)
# 开启线程
for thread in threads:
thread.start()
time.sleep(0.1)
# 发送事件通知
print '主线程通知小伙伴开吃咯!'
event.set()
运行结果:
Thread-1 已经启动
学好 Python 不论是就业还是做副业赚钱都不错,但要学会 Python 还是要有一个学习规划。最后大家分享一份全套的 Python 学习资料,给那些想学习 Python 的小伙伴们一点帮助!
### 一、Python所有方向的学习路线
Python所有方向路线就是把Python常用的技术点做整理,形成各个领域的知识点汇总,它的用处就在于,你可以按照上面的知识点去找对应的学习资源,保证自己学得较为全面。

### 二、学习软件
工欲善其事必先利其器。学习Python常用的开发软件都在这里了,给大家节省了很多时间。

### 三、全套PDF电子书
书籍的好处就在于权威和体系健全,刚开始学习的时候你可以只看视频或者听某个人讲课,但等你学完之后,你觉得你掌握了,这时候建议还是得去看一下书籍,看权威技术书籍也是每个程序员必经之路。

### 四、入门学习视频
我们在看视频学习的时候,不能光动眼动脑不动手,比较科学的学习方法是在理解之后运用它们,这时候练手项目就很适合了。

### 五、实战案例
光学理论是没用的,要学会跟着一起敲,要动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。

### 六、面试资料
我们学习Python必然是为了找到高薪的工作,下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料,并且有阿里大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。


**了解详情:https://docs.qq.com/doc/DSnl3ZGlhT1RDaVhV**