Python的多线程与多进程


多进程 Process

def run_something(name):
    print("这里使用 %s进程 处理 %s." % (os.getpid(), name))

if __name__ == '__main__':
    print("当前进程是: %s" % os.getpid())
    pro = Process(target=run_something, args=('Hello',))
    pro.start()
    pro.join()
    print("子进程结束.")

运行结果:

当前进程是: 9304
这里使用 9309进程 处理 Hello.
子进程结束.

子进程 subprocess

示例:

if __name__ == '__main__':
    print("$nslookup www.so.com:")
    sre = subprocess.call(['nslookup', 'www.so.com'])
    print("Exit ", sre)

运行结果:

$nslookup www.so.com:
Server:        127.0.1.1
Address:    127.0.1.1#53

Non-authoritative answer:
www.so.com    canonical name = so.qh-lb.com.
Name:    so.qh-lb.com
Address: 125.88.193.243

Exit  0

进程通信 Queue

示例:

# python 2.x
from Queue import Queue

def os_write(qu):
    print("当前 write 进程是: %s" % os.getpid())
    for i in range(5):
        print("通道装载数据: %d" % i)
        qu.put(i)
        time.sleep(random.random() * 2)


def os_read(qu):
    print("当前 read 进程是: %s" % os.getpid())
    while True:
        print("从通道中获取: ", qu.get(True))


if __name__ == '__main__':
    qu = Queue()
    pw = Process(target=os_write, args=(qu,))
    pr = Process(target=os_read, args=(qu,))
    pw.start()
    pr.start()
    pw.join()
    if qu.empty():
        pr.terminate()
    print("进程结束")

运行结果:

当前 write 进程是: 12670
通道装载数据: 0
当前 read 进程是: 12671
从通道中获取:  0
通道装载数据: 1
从通道中获取:  1
通道装载数据: 2
从通道中获取:  2
通道装载数据: 3
从通道中获取:  3
通道装载数据: 4
从通道中获取:  4
进程结束

多线程 Thread

# 导入Python标准库中的Thread模块
from threading import Thread

def run_loop():
    print("当前线程是: %s" % threading.current_thread().name)
    for i in range(6):
        print("线程 %s 处理 %d" % (threading.current_thread().name, i))
        time.sleep(random.random() * 2)
    print("线程 %s 结束." % threading.current_thread().name)


if __name__ == '__main__':
    print("当前线程是: %s" % threading.current_thread().name)
    # 创建一个线程
    td = Thread(target=run_loop, name="LoopThread")
    # 启动 刚创建的线程
    td.start()
    # 线程 等待 ( 等待子线程都执行完毕了,主线程再关闭 )
    td.join()
    print("线程 %s 结束." % threading.current_thread().name)

运行结果:

当前线程是: MainThread
当前线程是: LoopThread
线程 LoopThread 处理 0
线程 LoopThread 处理 1
线程 LoopThread 处理 2
线程 LoopThread 处理 3
线程 LoopThread 处理 4
线程 LoopThread 处理 5
线程 LoopThread 结束.
线程 MainThread 结束.

多线程与多进程的区别 ^1

多线程多进程 最大的不同在于, 多进程 中,同一个变量,各自有一份拷贝存在于每个进程中,互不影响,而多线程中,所有变量都由所有线程共享

使用继承类创建 ^2

from threading import Thread
# 创建一个类,必须要继承Thread
class MyThread(Thread):
    # 继承Thread的类,需要实现run方法,线程就是从这个方法开始的
    def run(self):
        # 具体的逻辑
        function_name(self.parameter1)

    def __init__(self, parameter1):
        # 需要执行父类的初始化方法
        Thread.__init__(self)
        # 设置守护线程
        self.setDaemon(True)
        # 如果有参数,可以封装在类里面
        self.parameter1 = parameter1

# 如果有参数,实例化的时候需要把参数传递过去
t = MyThread(parameter1)
# 同样使用start()来启动线程
t.start()

在__init__中,self实际上就是Thread类的对象,所以setDaemon实际上是Thread类的一个方法,当设置为True就可以把当前类变成一个守护线程,等到其他线程都停止以后,它会自动停止。

线程事件通知 ^2

from threading import Event, Thread

# 接收一个Event对象
def test_event(e):
    print('run...')
    # 让这个线程进入睡眠状态
    e.wait()
    # 当线程被唤醒以后,会输出下面的语句
    print('end...')

e = Event()
t = Thread(target=test_event, args=(e,))
# 这里会看到输出了 run...
t.start()

print('Set Event...')

# 唤醒线程会看到 end...
e.set()

注意:当我们程序在一起运行周期内,重复调用e.wait(),第二次调用就无法让线程进入休眠状态了,需要调用e.clear()清除以后,才能再次进入休眠状态。

创建线程本地数据 ^2

import threading

L = threading.local()
L.num = 1
# 此时操作的是我们当前主线程的threading.local()对象,输出结果为1
print(L.num)

def f():
    L.num = 5
    # 这里可以成功的输出5
    print(L.num)

# 创建一个子线程,去调用f(),看能否访问主线程中定义的L.num
t = threading.Thread(target=f)
t.start()
# 主线程中的L.num依然是1,没有发生任何改变
print(L.num)

threading.local()创建的对象中的属性,是对于每个线程独立存在的,它们相互之间无法干扰。


参考文档


Author: Itaken
Reprint policy: All articles in this blog are used except for special statements CC BY 4.0 reprint polocy. If reproduced, please indicate source Itaken !
  TOC目录