117 Python程序中的线程操作-开启多线程(threading.Thread)

一、python线程模块的选择

Python提供了几个用于多线程编程的模块,包括thread、threading和Queue等。thread和threading模块允许程序员创建和管理线程。thread模块提供了基本的线程和锁的支持,threading提供了更高级别、功能更强的线程管理的功能。Queue模块允许用户创建一个可以用于多个线程之间共享数据的队列数据结构。

避免使用thread模块,因为更高级别的threading模块更为先进,对线程的支持更为完善,而且使用thread模块里的属性有可能会与threading出现冲突;其次低级别的thread模块的同步原语很少(实际上只有一个),而threading模块则有很多;再者,thread模块中当主线程结束时,所有的线程都会被强制结束掉,没有警告也不会有正常的清除工作,至少threading模块能确保重要的子线程退出后进程才退出

thread模块不支持守护线程,当主线程退出时,所有的子线程不论它们是否还在工作,都会被强行退出。而threading模块支持守护线程,守护线程一般是一个等待客户请求的服务器,如果没有客户提出请求它就在那等着,如果设定一个线程为守护线程,就表示这个线程是不重要的,在进程退出的时候,不用等待这个线程退出。

二、threading模块

multiprocess模块的完全模仿了threading模块的接口,二者在使用层面,有很大的相似性,因而不再详细介绍(官方链接)

三、开启子线程的两种方式

线程的开启和进程不同,进程是拷贝一份代码去内存中执行。内部调用的是fork创建子进程

而线程是会去执行的指定函数

  1. 通过指定函数的方式
  2. 通过类的继承,实现run方法

方式1:

# 方式一
def task(name):
    print(f'{name} start')
    global x
    x -= 1
    print({name}, x)
    time.sleep(2)
    print(f'{name} end')


if __name__ == '__main__':
    x = 10
    t1 = Thread(target=task,args=("线程1",))
    t2 = Thread(target=task,args=("线程2",))
    t1.start()  # 告诉操作系统开一个线程
    t2.start()  # 告诉操作系统开一个线程

    print('主')

线程1 start
{'线程1'} 9
线程2 start
{'线程2'} 8

线程1 end
线程2 end

方式2

# 方式二
class Mythread(Thread):
    def __init__(self,name):
        super().__init__()
        self.name = name

    def run(self):
        print(f'{self.name} start')
        global x
        x -= 1
        print({self.name}, x)
        time.sleep(2)
        print(f'{self.name} end')

if __name__ == '__main__':
    x = 10
    t1 = Mythread("线程1")
    t2 = Mythread("线程2")
    t1.start()
    t2.start()
    print('主')

线程1 start
{'线程1'} 9
线程2 start
{'线程2'} 8

线程1 end
线程2 end

通过上面两组代码你会发现:线程的创建运行比进程快,同一个进程中的线程可以共享资源

四、join回收子线程

和进程一样,等待所以子线程结束然后去回收

from threading import Thread
import time
'''
等待回收子线程
'''

def task():
    print('子线程 start')
    time.sleep(2)
    print('子线程 end')

t = Thread(target=task)
t.start()
t.join() # 等待子线程运行结束
print('主线程')

五、Thread类的其他方法

Thread实例对象的方法:

  • isAlive():返回线程是否活动的。
  • getName():返回线程名。
  • setName():设置线程名。

threading模块提供的一些方法:

  • threading.currentThread():返回当前的线程变量。
  • threading.enumerate():返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后的线程。
  • threading.activeCount():返回正在运行的线程数量,与len(threading.enumerate())有相同的结果。
from threading import Thread,currentThread,enumerate,activeCount
import time
'''
线程的其他用法:
    1.查看是否存在  is_alive()    # True or False
    2.获取线程名    getName()     
    3.设置线程名    setName(name) 
    4.当前线程      currentThread()   需要从threading导入currentThread模块
    5.活动线程总和  activeCount()     需要从threading导入activeCount模块
    6.查看所有线程  enumerate()       需要从threading导入enumerate模块
'''
def task():
    print('子线程 start')
    time.sleep(2)
    print('子线程 end')

if __name__ == '__main__':
    t1 = Thread(target=task)
    t2 = Thread(target=task)
    t1.start()
    t2.start()

    print("查看线程状态,设置线程名,获取线程名","-" * 50)
    print(t1.is_alive())  # 查看是否存在
    print(t2.is_alive())  # 查看是否存在
    t1.setName("子线程一")  # 设置线程1名字
    t2.setName("子线程二")  # 设置线程2名字
    print(t1.getName()) # 获取线程名
    print(t2.getName()) # 获取线程名


    print("查看当前线程","-" * 50)
    print(currentThread())      # 查看当前线程
    print(currentThread().name)  # 查看当前线程名
    print("查看所有线程","-"*50)
    print(activeCount())    # 查看存活线程个数
    print(enumerate())  # 查看所有线程
    print(len(enumerate())) # 查看所有线程个数

六、基于多线程实现socket多用户间通讯

客户端

import socket
from threading import Thread

def task(conn,client_addr):
    # 通讯循环
    while 1:
        try:
            msg = conn.recv(1024)
            if not msg:
                break
            print(client_addr,"消息:",msg.decode("utf8"))
            msg = input("请输入内容")
            conn.send(msg.encode("utf8"))
        except Exception as e:
            print(e)
            break

if __name__ == '__main__':
    server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    server.bind(("127.0.0.1",8080))
    server.listen(5)

    # 链接循环
    while 1:
        print("等待连接...")
        conn, addr = server.accept()
        print(addr,"连接成功")
        t = Thread(target=task,args=(conn,addr))
        t.start()

客户端

import socket

client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
client.connect(("127.0.0.1",8080))

while 1:
    msg = input("请输入内容")
    client.send(msg.encode("utf8"))
    data = client.recv(1024)
    if not data:
        break
    print(data.decode("utf8"))

转载于:https://www.cnblogs.com/XuChengNotes/p/11552831.html

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值