1、线程的介绍
2、线程与进程的区别
例子。
import threading
import time
def fun(num):
print("线程执行%d"%num)
time.sleep(2)
# 执行5个形参
for i in range(5):
t = threading.Thread(target=fun, args=(i+1,)) # 设置线程
t.start() # 启动线程
3、 查看帮助信息及参数信息
import threading
print(help(threading.Thread))
4、 查看当前形参数量
# coding=utf-8
import threading
from time import sleep, ctime
def sing():
for i in range(3):
print("傻不傻%d" % i)
sleep(1)
def dance():
for i in range(3):
print("????%d" % i)
sleep(1)
if __name__ == '__main__':
print('___开始___%s' % ctime()) # 获取当前时间,字符串表示没,读格式
t1 = threading.Thread(target=sing)
t2 = threading.Thread(target=dance)
t1.start()
t2.start()
while True:
length = len(threading.enumerate())
print("当前运行的线程数为:%d" % length)
if length<=1: # 等于就只剩一个主线程,说明副线程都运行完了
break
sleep(0.5)
5、子类化线程类
# coding=utf-8
import threading
import time
class MyThread(threading.Thread):
def __init__(self, num, str1):
super().__init__()
self.num = num
self.str1 = str1
def run(self):
for i in range(3):
time.sleep(1)
msg = "I am " + self.name + " @" + str(i) + " num:" + str(self.num) + "str1:" + self.str1 # name属性中报错的是当前线程的
print(msg)
if __name__ == '__main__':
t = MyThread(10, "abc")
t.start()
6、线程的几种状态
7、线程共享全局变量
# coding=utf8
from threading import Thread
import time
g_num = 100
def work1():
global g_num
for i in range(3):
g_num += 1
print("---in work1.g_num is %d---" % g_num)
def work2():
global g_num
print("---in work2.g_num is %d---" % g_num)
print("----创建线程之前g_num is %d---" % g_num)
t1 = Thread(target=work1())
t1.start()
# 延迟一会,保证线程中的事情做完
t2 = Thread(target=work2())
t2.start()
8、用传参的方式使用全局变量
例子一;全局变量为不可变对象
# coding=utf8
from threading import Thread
import time
g_num = 100
def work1(num):
for i in range(3):
num += 1
print("---in work1.g_num is %d---" % num)
def work2(num):
print("---in work2.g_num is %d---" % num)
print("----创建线程之前g_num is %d---" % g_num)
t1 = Thread(target=work1, args=(g_num,))
t1.start()
# 延迟一会,保证线程中的事情做完
t2 = Thread(target=work2, args=(g_num,))
t2.start()
print("----创建线程之后g_num is %d---" % g_num)
输出:
----创建线程之前g_num is 100---
---in work1.g_num is 101---
---in work1.g_num is 102---
---in work1.g_num is 103---
---in work2.g_num is 100---
----创建线程之后g_num is 100---
第二个例子:全局变量为可变对象
# coding=utf8
from threading import Thread
import time
g_num = [11, 22, 33]
def work1(num):
for i in range(3):
num.append(44)
print("---in work1.g_num is %s---" % num)
def work2(num):
print("---in work2.g_num is %s---" % num)
print("----创建线程之前g_num is %s---" % g_num)
t1 = Thread(target=work1, args=(g_num,))
t1.start()
# 延迟一会,保证线程中的事情做完
t2 = Thread(target=work2, args=(g_num,))
t2.start()
print("----创建线程之后g_num is %s---" % g_num)
输出
----创建线程之前g_num is [11, 22, 33]---
---in work1.g_num is [11, 22, 33, 44]---
---in work1.g_num is [11, 22, 33, 44, 44]---
---in work1.g_num is [11, 22, 33, 44, 44, 44]---
---in work2.g_num is [11, 22, 33, 44, 44, 44]---
----创建线程之后g_num is [11, 22, 33, 44, 44, 44]---
9、线程同步问题
例子1
coding=utf8
import threading
import time
g_num = 0
def work1():
global g_num
for i in range(10):
g_num += 1
for i in range(2):
t = threading.Thread(target=work1)
t.start()
print("----创建线程之后g_num is %s---" % g_num)
输出
----创建线程之后g_num is 20---
例子2
把上面代码中的 for i in range(10):
改成 for i in range(1000000):
输出
----创建线程之后g_num is 219002---
按理说应该输出2000000,但是结果不是,这是因为2个线程之间
进程在运行的时候,数据是放在内存里的,而CPU在运算的时候,数据是要读在数据的寄存器里的(CPU中有很多寄存器),然后再在寄存器中对数据进行操作,最后再写会内存里。
在上面代码中
10、线程同步-给线程加锁
创建锁
mutex = threading.Lock()
锁定
mutex.acquire([blocking])
如果没有设定block为True,则当前线程会堵塞,直到获取这个锁为止(如果没有指定,默认为True)
如果设定blocking为False,则当前线程不会堵塞
释放
mutex.relesse()
例子:加了一个互斥锁,成功输出结果
# coding=utf8
import threading
import time
class Task1(threading.Thread):
def run(self):
while True:
if lock1.acquire():
print("---Task1---")
time.sleep(1)
lock2.release()
class Task2(threading.Thread):
def run(self):
while True:
if lock2.acquire():
print("---Task2---")
time.sleep(1)
lock3.release()
class Task3(threading.Thread):
def run(self):
while True:
if lock3.acquire():
print("---Task3---")
time.sleep(3)
lock1.release()
lock1 = threading.Lock()
lock2 = threading.Lock()
lock2.acquire()
lock3 = threading.Lock()
lock3.acquire()
t1 = Task1()
t2 = Task2()
t3 = Task3()
t1.start()
t2.start()
t3.start()
通过3把锁固定线程执行的顺序,执行完线程t1,然后执行线程t2,然后执行线程t3,然后依次循环。
12、queue的使用
# coding=utf8
import threading
import time
from queue import Queue
class Producter(threading.Thread):
def run(self):
while True:
if queue.qsize() < 1000:
for x in range(100):
msg = "产品" + str(x)
print("%s创建了%s"%(self.name, msg))
queue.put(msg)
time.sleep(1)
class Consumer(threading.Thread):
def run(self):
while True:
if queue.qsize() > 100:
for x in range(3):
msg = queue.get()
print("%s消费了%s"%(self.name, msg))
time.sleep(0.5)
queue = Queue()
for i in range(500):
msg = "产品" + str(i)
queue.put("msg")
for i in range(2):
t = Producter()
t.start()
for i in range(5):
c = Consumer()
c.start()
13、ThreadLocal 变量