线程是依赖于进程,一个进程简单理解为一个应用程序
每个进程默认都会包含一个主线程
线程是程序执行的路径,它可以实现进程并发的多任务处理
创建线程:
threading.Thread()
启动线程:
threading.start()
代码理解:
import threading
import time
def sleeper(n, name):
print('我是{}准备睡觉'.format(name))
time.sleep(n)
print('{}从睡眠中醒来'.format(name))
# 创建线程,并启动线程
t = threading.Thread(target=sleeper, name='mythread', args=(5, 'bob'))
t.start()
t.join()
# 获取当前进程中线程的个数
print(threading.active_count())
# 获取当前线程的名字
print(threading.currentThread().getName())
线程的作用
1、节省资源开销
2、充分利用CPU资源
3、尤其是在GUI中,如果耗时操作不使用线程就会造成程序的阻塞
代码理解:
开线程于不开线程的差距在效率体现
import threading
import time
def sleeper(n, name):
print('我是{}准备睡觉'.format(name))
time.sleep(n)
print('{}从睡眠中醒来'.format(name))
threads_list = []
start = time.time()
for i in range(5):
t = threading.Thread(target=sleeper, name='thread{}'.format(i), args=(5, 'thread{}'.format(i)))
threads_list.append(t)
t.start()
print("{} 已经启动了".format(t.name))
for t in threads_list:
t.join()
end = time.time()
print('耗费时间是{}'.format(end-start))
print('所有线程执行完毕')
# 不使用线程
def sleeper(n, name):
print('我是{}准备睡觉'.format(name))
time.sleep(n)
print('{}从睡眠中醒来'.format(name))
start = time.time()
for i in range(5):
print('第{}次调用'.format(i))
sleeper(5, i)
end = time.time()
print('不用线程耗费时间{}'.format(end-start))
print('主线程结束')
后台线程
后台线程和前台线程几乎完全相同,只有一处不同,即后台线程不会确保执行环境一直运行
一旦程序中的所有前台程序都停止,系统会停止并关闭所有后台线程
代码理解:
import threading
import time
def create_item_1():
global total
for i in range(10):
time.sleep(2)
total += 1
print('creator1 add item')
print('creator1 has done')
def create_item_2():
global total
for i in range(7):
time.sleep(2)
total += 1
print('creator2 add item')
print('creator2 has done')
def limit_items():
global total
while True:
if total > 5:
print('overload')
total -= 3
print("subtracted 3")
else:
time.sleep(1)
print('waiting')
creator1 = threading.Thread(target=create_item_1)
creator2 = threading.Thread(target=create_item_2)
# 创建线程的时候将daemon设置True
# 后台线程不能jion
limitor = threading.Thread(target=limit_items(), daemon=True)
creator1.start()
creator2.start()
limitor.start()
creator1.join()
creator2.join()
自定义线程
1、继承Thread类,重写__init__,run方法
2、启动线程调用start方法
代码理解:
import threading
import time
def display(name, delay):
count = 0
while count < 5:
time.sleep(delay)
count += 1
print(name, '-------', time.time())
class MyThread(threading.Thread):
def __init__(self, name, delay):
threading.Thread.__init__(self)
self.name = name
self.delay = delay
def run(self) -> None:
print('start thread')
display(self.name, self.delay)
print('end thread')
t = threading.Thread(target=display, args=('thread', 5))
t.start()
线程同步与锁
多线程对于共享数据需要进行同步处理---通过Lock机制处理
import threading
import time
import sys
import os
tickets = 1000
lock = threading.Lock()
def do_tickets(name):
global tickets
while True:
lock.acquire()
if tickets != 0:
print(name + '卖票')
tickets -= 1
print('余票{}张'.format(tickets))
else:
print('票已卖完!')
os._exit(0)
lock.release()
def man_task():
t1 = threading.Thread(target=do_tickets, args=('thread1'))
t2 = threading.Thread(target=do_tickets, args=('thread2'))
t3 = threading.Thread(target=do_tickets, args=('thread3'))
t1.start()
t2.start()
t3.start()
if __name__ == '__main__':
man_task()