lhl
首页
python
leetcode
产品思想
软件测试
博客 (opens new window)
github (opens new window)
首页
python
leetcode
产品思想
软件测试
博客 (opens new window)
github (opens new window)
  • python

    • Python 基础

    • Python 数据库

    • 面向对象

    • Python Web

    • Python 进阶

      • 协程
      • 装饰器
      • decorator
      • filter
      • 列表生成式
      • 进程&线程
        • 进程&线程
      • 生成器
      • 匿名函数
      • map&&reduce
      • venv
  • leetcode

  • 软件测试

  • Git

  • linux

  • 产品

  • MySql

  • docker

  • python
  • 进阶
2023-07-18
目录

进程&线程

# 进程&线程

# 概念

对于操作系统来说,一个任务就是一个进程(Process),比如打开一个浏览器就是启动一个浏览器进程,打开一个记事本就启动了一个记事本进程,打开两个记事本就启动了两个记事本进程,打开一个Word就启动了一个Word进程。

有些进程还不止同时干一件事,比如Word,它可以同时进行打字、拼写检查、打印等事情。在一个进程内部,要同时干多件事,就需要同时运行多个“子任务”,我们把进程内的这些“子任务”称为线程(Thread)。

# 进程

# 简单使用

from multiprocessing import Process
import os


## 子进程要执行的代码
def run_proc(name):
    print('run child process %s (%s)...' % (name, os.getpid()))

if __name__ == '__main__':
    print('parent process id: %s.' % os.getpid())
    ## args是元组,当元组一个元素是,记得加逗号,
    p = Process(target=run_proc, args=('test', ))
    print('child process will start.')
    p.start()
    ## 等子进程结束再继续往下执行
    p.join()
    print('child process will end')

  1. multiprocessing模块下的 Process 类(ps:首字母大写)
  2. p = Process(target=run_proc, args=('test', )),创建一个子进程, args, 需要的是一个元组,元组一个元素记得要加逗号
  3. p.start(),子进程开始
  4. p.join(),等子进程结束再继续往下执行

# 进程池

from multiprocessing import Pool
import os, time, random

def long_time_task(name):
    print('run task %s (%s)...' % (name, os.getpid()))
    start = time.time()
    time.sleep(random.random() * 3)
    end = time.time()
    print('task %s run %.2f seconds' % (name, end - start))


if __name__ == '__main__':
    print('parent process %s.' % os.getpid())
    ## 限制进程池的大小,只能同时跑4个线程
    p = Pool(4)
    for i in range(5):
        p.apply_async(long_time_task, args=(i,))
    print('wait for all subprocesses done...')
    p.close()
    ## 对Pool对象调用join()方法会等待所有子进程执行完毕
    ## 调用join()之前必须先调用close(),调用close()之后就不能继续添加新的Process了
    p.join()
    print('all sub process done...')
  1. multiprocessing模块下的 Pool 类(ps:首字母大写)
  2. p = Pool(4),限制进程池的大小,只能同时跑4个线程
  3. p.join(),对Pool对象调用join()方法会等待所有子进程执行完毕,调用join()之前必须先调用close(),调用close()之后就不能继续添加新的Process了

# 进程通信

进程间通信是通过Queue、Pipes等实现的。

from multiprocessing import Process, Queue
import os, time, random

def write(q):
    print('process to write: %s' % os.getpid())
    for value in ['A', 'B', 'C']:
        print('put %s to queue...' % value)
        q.put(value)
        time.sleep(random.random())

def read(q):
    print('process to read: %s' % os.getpid())
    ## 这是个死循环,必须要有终止条件
    while True:
        value = q.get(True)
        print('Get %s from queue.' % value)

if __name__ == '__main__':
    ## 父进程创建 queue, 并传给各个子进程
    q = Queue()
    pw = Process(target=write, args=(q,))
    pr = Process(target=read, args=(q,))
    ## 启动子进程 pr和 pw
    pw.start()
    pr.start()

    ## 等待 pw 结束
    pw.join()

    ## pr 进程里是死循环,只能强行终止
    pr.terminate()
  1. multiprocessing模块下的 Queue 类(ps:首字母大写)
  2. pw = Process(target=write, args=(q,)),pr = Process(target=read, args=(q,)),创建一个读进程和写进程
  3. pr.terminate(),pr 进程里是死循环,只能强行终止

# 线程

# 简单使用

Python的标准库提供了两个模块:_thread和threading,_thread是低级模块,threading是高级模块,对_thread进行了封装。绝大多数情况下,我们只需要使用threading这个高级模块。

import time, threading

## 新线程执行的代码
def loop():
    print('thread %s is running' % threading.current_thread().name)
    n = 0
    while n < 5:
        n = n + 1
        print('thread %s >>> %s' % (threading.current_thread().name, n))
        time.sleep(1)
    print('thread %s ended.' % threading.current_thread().name)


print('thread %s is running' % threading.current_thread().name)
## 启动线程就是把一个函数传入并创建 Thread 实例, 然后调用 start()开始执行
t = threading.Thread(target=loop, name='LoopThread')
t.start()
t.join()
print('thread %s is ended' % threading.current_thread().name)
  1. t = threading.Thread(target=loop, name='LoopThread'), 启动线程就是把一个函数传入并创建 Thread 实例, 然后调用 start()开始执行

# 锁

import time, threading
## 假设这是存款
balance = 0
## 锁初始化
lock = threading.Lock()
def change_it(n):
    ## 先存后去,结果应该为0
    global balance
    balance = balance + n
    balance = balance - n


def run_thread(n):
    for i in range(2000000):
        ## 先获取锁
        lock.acquire()
        try:
            ## 操作
            change_it(n)
        finally:
            ## 最后记得释放锁
            lock.release()



t1 = threading.Thread(target=run_thread, args=(5, ))
t2 = threading.Thread(target=run_thread, args=(8, ))
t1.start()
t2.start()

t1.join()
t2.join()
print(balance)

  1. lock = threading.Lock(), 锁初始化
  2. lock.acquire(), 先获取锁
  3. try: pass,进行操作, finally: lock.release(),释放锁

# ThreadLocal

import threading

## 全局ThreadLocal 对象
local_school = threading.local()


def process_student():
    ## 获取当前线程关联的student
    std = local_school.student
    print('hello, %s in (%s)' % (std, threading.current_thread().name))


def process_thread(name):
    ## 绑定ThreadLocal 的 student
    local_school.student = name
    process_student()

if __name__ == '__main__':
    t1 = threading.Thread(target=process_thread, args=('lv',), name='Thread-1')
    t2 = threading.Thread(target=process_thread, args=('wang',), name='Thread-2')
    t1.start()
    t2.start()
    t1.join()
    t2.join()
  1. local_school = threading.local(), 全局ThreadLocal
  2. process_student函数std = local_school.student,将ThreadLocal 的 student拿出来
  3. process_thread 函数local_school.student = name,绑定ThreadLocal 的 student

# 多线程 vs 多进程

两种模型的优劣 (opens new window)

列表生成式
生成器

← 列表生成式 生成器→

最近更新
01
lhl learn notes
02
filter
06-09
03
decorator
06-09
更多文章>
Theme by Vdoing
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式