Python并行编程(一):线程的基本概念和线程的两种定义方法以及join()、setDaemon(True)的使用

前言:本系列将包含Python并行编程的相关技术内容,包括Python线程、Python进程、并发编程的异步模式及终极大法Python分布式计算如Celery、SCOOP等相关技术。

关键词: threading multiprocessing asyncio Celery


线程的基本概念和线程的两种定义方法

线程是什么?

线程看起来就像轻量级的进程,而进程又是什么呢? 进程即咱们平时运行程序,好比经过点击图标打开的浏览器,QQ都是进程,进程拥有本身的独立的内存空间地址,能够拥有多个线程;即线程是存在进程内,也就意味着一个进程内的线程能够共享一些资源,其线程间的切换也就比进程低得多,多个线程能够并行及并发执行,共享数据和资源,因此咱们多数时候的线程通讯都是利用共享信息的空间进行通讯,这也是后面谈到的线程管理必备的多种线程通讯方式了。python

在Python怎么定义线程?

使用线程最简单的方式就是经过目标函数的实例化:

import threading
import time


# 用于实例化线程目标函数
def function(i):
    time.sleep(2)
    print('Thread {} is running.'.format(i))
    time.sleep(2)
    return


for i in range(5):
    # Python模块threading.Thread方法
    t = threading.Thread(target=function, args=(i, ))
    t.start()
复制代码

运行截图以下: 编程

运行截图
经过以上程序咱们看出,定义好咱们须要运行的目标函数来实例化线程,而后传入参数 target即函数名,而后若是须要运行的目标函数有参数须要传递的话便可传入 args元组,注意此处传入的是 元组tuple。 而后咱们在调用 start()方法后启动实例化的线程

使用线程模块实现新的线程:

import threading
import time


class myThread(threading.Thread):
    def __init__(self, i):
        threading.Thread.__init__(self)
        self.i = i

    def run(self):
        time.sleep(2)
        print('Thread {} is running.'.format(self.i))
        time.sleep(2)
        return


for i in range(1, 6):
    t = myThread(i)
    t.start()
复制代码

运行截图以下: 浏览器

运行截图
经过上面的程序咱们能够看出,咱们须要定义新的Thread类的子类,而且经过重写 __init__方法来传递参数,而后重写 run()方法来实现目标函数,那么当咱们建立出新的子类后就能够实例化该子类并经过 start()方法来启动线程。

守护线程 setDaemon(True)

接下来咱们在运行一段代码:多线程

import threading
import time


class myThread(threading.Thread):
    def __init__(self, i):
        threading.Thread.__init__(self)
        self.i = i

    def run(self):
        time.sleep(2)
        print('Thread {} is running.'.format(self.i))
        time.sleep(2)
        return

print('Mian THread starting')

for i in range(1, 6):
    t = myThread(i)
    t.start()
    
print('Mian THread end')
复制代码

运行截图以下: 并发

运行截图
当一个进程启动以后,会默认产生一个主线程,由于线程是程序执行流的最小单元,当设置多线程时,主线程会建立多个子线程;咱们在主线程添加了两句 print()用于打印主线程的运行状态,咱们能够看见在默认状况下主现成直接执行完就退出了,此时子线程们还在执行过程当中,那么若是咱们添加setDaemon(True)方法呢:

import threading
import time


class myThread(threading.Thread):
    def __init__(self, i):
        threading.Thread.__init__(self)
        self.i = i

    def run(self):
        time.sleep(2)
        print('Thread {} is running.'.format(self.i))
        time.sleep(2)
        return

print('Mian THread starting')

for i in range(1, 6):
    t = myThread(i)
    t.setDaemon(True)
    t.start()
    
print('Mian THread end')
复制代码

运行截图以下: app

运行截图
咱们能够在运行截图中看到,当咱们使用setDaemon(True)方法,设置子线程为守护线程时,主线程一旦执行结束,则所有线程所有被终止执行,可能出现的状况就是,子线程的任务尚未彻底执行结束,就被迫中止。 那么咱们能不能让主线程等等咱们的子线程,等待子线程运行结束后,主线程再终止呢,即实现守护线程相反的效果,答案是能够得。

阻塞线程 join()

import threading
import time


class myThread(threading.Thread):
    def __init__(self, i):
        threading.Thread.__init__(self)
        self.i = i

    def run(self):
        time.sleep(2)
        print('Thread {} is running.'.format(self.i))
        time.sleep(2)
        return


print('Mian THread starting')

threads = []
for i in range(1, 6):
    t = myThread(i)
    t.start()
    threads.append(t)

for t in threads:
    t.join()
    
print('Mian THread end')

复制代码

运行截图以下: 异步

运行截图
咱们能够看见主线程是在等待子线程运行结束才终止运行的,即 join()所完成的工做就是线程同步,即主线程任务结束以后,进入阻塞状态,一直等待其余的子线程执行结束以后,主线程再终止。
相关文章
相关标签/搜索