目录
线程
一、初识线程
1.1 什么是线程
进程只是用来把资源集中到一起(进程只是一个资源单位,或者说资源集合),而线程才是cpu上的执行单位。
多线程(即多个控制线程)的概念是,在一个进程中存在多个控制线程,多个控制线程共享该进程的地址空间,相当于一个车间内有多条流水线,都共用一个车间的资源。
1.2 线程和进程的区别
线程 | 进程 |
---|---|
同一个进程下的线程资源共享 | 内存空间彼此隔离 |
快:只是告诉操作系统一个执行方案 | 慢:需要申请资源开辟空间 |
二、开启线程的两种方式
'''方式一'''
from threading import Thread
import time
def task():
print('子线程开始')
time.sleep(1)
print('子线程结束')
if __name__ == '__main__':
t = Thread(target=task) #初始化一个对象
t.start()
time.sleep(2)
print('主线程结束')
'''方式二(继承类的方式)'''
from threading import Thread
import time
class task(Thread):
print('子线程开始')
time.sleep(1)
print('子线程结束')
t = task()
t.start()
time.sleep(2)
print('主线程结束')
三、线程和进程速度对比
from multiprocessing import Process
from threading import Thread
import time
def task(name):
print(f"{name}在运行")
time.sleep(3)
print(f"{name}结束")
if __name__ == '__main__':
p = Process(target=task,args=('子进程',))
t = Thread(target=task,args=('子线程',))
p.start()
t.start()
time.sleep(5)
print('主')
'''
子线程在运行
子进程在运行
子线程结束
子进程结束
主
### 充分证明了线程比进程快
'''
四、证明子线程共享资源
from threading import Thread
x = 100
def task():
global x
x = 1
if __name__ == '__main__':
t = Thread(target=task)
t.start()
print(x) #如果x被改为1,则证明子线程共享资源 #1
'''
综上所述,充分证明子线程共享资源
'''
五、线程的相关方法
5.1 join方法——(等待子进程)
from threading import Thread
import time
def task(name,n):
print(f'{name}开始')
time.sleep(n)
print(f'{name}结束')
if __name__ == '__main__':
t1 = Thread(target=task,args=('子线程1',1))
t2 = Thread(target=task,args=('子线程2',2))
t3 = Thread(target=task,args=('子线程3',3))
l = [t1,t2,t3]
for t in l:
t.start()
t.join() #感知子线程的结束
print('主线程结束')
print(t.is_alive()) #查看t线程是否还活着,false 证明死了
5.2其他方法
'''
Thread实例对象的方法
# isAlive(): 返回线程是否活动的。
# getName(): 返回线程名。
# setName(): 设置线程名。
threading模块提供的一些方法(这些模块需要提前导入):
# threading.currentThread(): 返回当前的线程变量。
# threading.enumerate(): 返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后的线程。
# threading.activeCount(): 返回正在运行的线程数量,与len(threading.enumerate())有相同的结果。
'''
from threading import Thread,current_thread,enumerate,active_count
import time
def task(name,n):
print(f'{name}开始')
time.sleep(n)
print(f'{name}结束')
if __name__ == '__main__':
t1 = Thread(target=task,args=('子线程1',1))
t2 = Thread(target=task,args=('子线程2',2))
l = [t1,t2]
for t in l:
t.start()
print(t1.is_alive()) # 查看t1线程是否还活着 #True证明还活着
print(t1.getName()) #获取t1线程名
t1.setName('大猪蹄子线程')
print(t1.getName()) #获取修改后的t1线程名
print(current_thread()) # 返回当前线程
print(enumerate()) #返回当前运行的线程的一个列表
print(active_count()) #返回当前正在运行的线程数量
t.join()
print('主线程结束')
'''
子线程1开始
子线程2开始
True
Thread-1
大猪蹄子线程
<_MainThread(MainThread, started 13384)>
[<_MainThread(MainThread, started 13384)>, <Thread(大猪蹄子线程, started 1736)>, <Thread(Thread-2, started 10788)>]
3
子线程1结束
子线程2结束
主线程结束
'''
六、守护线程
守护线程守护的是进程的运行周期
- 对于主进程来说,运行完毕指的是主进程代码运行完毕‘
- 对于主线程来说运行完毕指的是主线程所在的进程内所有非守护线程统统运行完毕,主线程才算运行完毕
from threading import Thread
import time
def task1():
print('守护线程1开始')
time.sleep(2)
print('守护线程1结束')
print(t1.is_alive()) # True 当守护线程1结束了,守护线程1并没有死亡,也是在等待其他线程运行完毕
def task2():
print('子线程2开始')
time.sleep(3)
print('子线程2结束')
print(t1.is_alive()) # false 当子线程2结束了,守护线程1就死了
if __name__ == '__main__':
t1 = Thread(target=task1) #初始化一个对象
t2 = Thread(target=task2) #初始化一个对象
t1.daemon = True #必须在start开始之前将它设置为守护进程
t1.start()
t2.start()
time.sleep(2)
print('主线程结束')
print(t1.is_alive()) #True 他没有因为主线程的结束而结束,而是等待子线程2运行完毕
'''
守护线程1开始
子线程2开始
主线程结束
True
守护线程1结束
True
子线程2结束
False
'''
七、多线程实现socket
'''服务器'''
import socket
from threading import Thread
sk_s = socket.socket() #实例化
sk_s.bind(('127.0.0.1',8080)) #绑定
sk_s.listen(5) #监听
def task(conn): #子线程
while True: #通信循环
msg = conn.recv(1024) #接收线程
conn.send(msg.upper()) #发送数据
if __name__ == '__main__':
while True: # 链接循环
print('等待客户端连接>>>>')
conn, addr = sk_s.accept() #等待接收
print(f'客户端{addr}连接成功')
t = Thread(target=task,args=(conn,)) #实例化一个线程t
t.start() #子线程开始
'''客户端'''
import socket
sk_c = socket.socket()
sk_c.connect(('127.0.0.1',8080))
while True:
msg = input('>>>').strip()
if msg == "q":
break
msg = msg.encode('utf8')
sk_c.send(msg)
data = sk_c.recv(1024)
print(data.decode('utf8'))
sk_c.close()