多线程操作

【一】threading模块开启线程的两种方式

【1】直接调用Thread

from threading import Thread
import time


def task(name):
    print(f'{name} is starting')
    time.sleep(3)
    print(f'{name} is ending')


def main():
    t = Thread(target=task, args=("drake",))
    # 创建线程的开销非常小,几乎代码运行的一瞬间线程就已经创建了
    t.start()


if __name__ == '__main__':
    main()
# drake is starting
# drake is ending

【2】继承Thread父类

from threading import Thread
import time


class MyThread(Thread):
    def __init__(self, name):
        super().__init__()
        self.name = name

    def run(self):
        print(f'{self.name} is starting')
        time.sleep(3)
        print(f'{self.name} is ending')


def main():
    t1 = MyThread('dream')
    t2 = MyThread('uzi')
    t1.start()
    t2.start()


if __name__ == '__main__':
    main()

# dream is starting
# uzi is starting
# uzi is ending
# dream is ending

【三】一个进程下开启多个线程和多个子进程的区别

【1】谁的开启速度快

from threading import Thread
from multiprocessing import Process
import time


def work():
    print('hello')


def timer(func):
    def inner(*args, **kwargs):
        start_time = time.time()
        res = func(*args, **kwargs)
        print(f'函数 {func.__name__} 运行时间为:{time.time() - start_time}')
        return res

    return inner


@timer
def work_process():
    # 在主进程下开启子进程
    t = Process(target=work)
    t.start()


@timer
def work_thread():
    # 在主进程下开启线程
    t = Thread(target=work)
    t.start()


if __name__ == '__main__':
    work_thread()
    work_process()
# hello
# 函数 work_thread 运行时间为:0.0009613037109375
# 函数 work_process 运行时间为:0.03390765190124512
# hello

【2】查看pid

from threading import Thread
from multiprocessing import Process
import os


def work():
    print(f"该程序pid:{os.getpid()}")


def work_thread():
    # 在主进程下开启多个线程,每个线程都跟主进程的pid一样
    t1 = Thread(target=work)
    t2 = Thread(target=work)
    t1.start()
    t2.start()


def work_process():
    # 开多个进程,每个进程都有不同的pid
    p1 = Process(target=work)
    p2 = Process(target=work)
    p1.start()
    p2.start()


if __name__ == '__main__':
    work_thread()
    # 该程序pid:100620
    # 该程序pid:100620
    work_process()
    # 该程序pid:100772
    # 该程序pid:103280

【3】同一进程内的线程共享该进程的数据

from threading import Thread
from multiprocessing import Process


def work():
    global num
    num = 0


def work_process():
    num = 100
    p = Process(target=work)
    p.start()
    p.join()
    print(f'进程num:{num}')  # 子进程p已经将自己的全局的n改成了0,但改的仅仅是它自己的,查看父进程的n仍然为100
    # 进程num:100


def work_thread():
    num = 1
    t = Thread(target=work)
    t.start()
    t.join()
    print(f'线程num:{num}')  # 查看结果为1,因为同一进程内的线程之间共享进程内的数据
    # 线程num:1


if __name__ == '__main__':
    # 多进程:子进程只改自己的
    work_process()
    # 多线程:数据发生错乱,同一进程内的线程之间共享数据
    work_thread()

【四】多线程并发的服务端

  • 服务端
from threading import Thread
from socket import *


# 不写参数:默认是TCP协议
# 创建服务器对象
server = socket()
# 绑定 IP PORT
IP = '127.0.0.2'
PORT = 8081
ADDR = (IP, PORT)
server.bind(ADDR)
# 监听
server.listen(5)


# 将接受处理数据部分封装成函数调用
def run(conn):
    while True:
        from_client = conn.recv(1024)
        # 接受的信息为空时,会无限循环
        if len(from_client) == 0:
            break
        # 接收到客户端的信息
        print(f"这是来自客户端的消息:{from_client.decode()}")
        # 返回给客户端信息
        to_client = '你的消息我已收到!'
        conn.send(to_client.encode())
    # 关闭链接
    conn.close()


def main():
    while True:
        # 接受连接对象和 ip port
        conn, addr = server.accept()
        t = Thread(target=run, args=(conn,))
        t.start()


if __name__ == '__main__':
    main()
  • 客户端
from socket import *

# 不写参数:默认是TCP协议
# 创建客户端对象
client = socket()

# 绑定 IP PORT
IP = '127.0.0.2'
PORT = 8081
ADDR = (IP, PORT)
client.connect(ADDR)

while True:
    # 向服务端发数据
    message = input("请输入发送给服务端的消息:").strip()
    client.send(message.encode())

    # 接受服务器返回的数据
    data_from_server = client.recv(1024)
    print(data_from_server.decode())

【五】线程对象的属性和方法

【1】线程对象的 join 方法

from threading import Thread
import time


def task(name):
    print(f'{name} is starting')
    time.sleep(3)
    print(f'{name} is ending')


def main():
    t1 = Thread(target=task, args=('drake',))
    t2 = Thread(target=task, args=('uzi',))
    t1.start()
    t2.start()
    # 主线程等待子进程结束之后再运行
    t1.join()
    t2.join()


if __name__ == '__main__':
    main()
    # drake is starting
    # uzi is starting
    # drake is ending
    # uzi is ending

【2】获取当前进程的名字——current_thread

from threading import Thread, active_count, current_thread
import time


def task():
    # 获取当前线程的名字
    print(f'该线程的名字:{current_thread().name}')
    time.sleep(2)


def main():
    t1 = Thread(target=task)
    t2 = Thread(target=task)
    t1.start()
    t2.start()
    print(f'该线程的名字:{current_thread().name}')


if __name__ == '__main__':
    main()
    # 该线程的名字:Thread - 1(task)
    # 该线程的名字:Thread - 2(task)
    # 该线程的名字:MainThread

【3】统计当前活跃的线程数——active_count

from threading import Thread, active_count, current_thread
import time


def task():
    # 获取当前线程的名字
    print(f'该线程的名字:{current_thread().name}')
    time.sleep(2)


def main():
    t1 = Thread(target=task)
    t2 = Thread(target=task)
    t1.start()
    t2.start()
    # 统计当前活跃的线程数
    print(f'当前活跃的线程数:{active_count()}')
    print(f'该线程的名字:{current_thread().name}')


if __name__ == '__main__':
    main()
    # 该线程的名字:Thread - 1(task)
    # 该线程的名字:Thread - 2(task)
    # 当前活跃的线程数:3
    # 该线程的名字:MainThread
posted @ 2024-05-29 12:26  Ligo6  阅读(14)  评论(0)    收藏  举报