龙空技术网

Python并行编程(一):线程的基本概念和线程的两种定义方法

若数 249

前言:

目前咱们对“python子线程和主线程的关系”大约比较注重,兄弟们都需要分析一些“python子线程和主线程的关系”的相关知识。那么小编在网络上收集了一些有关“python子线程和主线程的关系””的相关文章,希望小伙伴们能喜欢,兄弟们快快来了解一下吧!

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

关键词: threading multiprocessing asyncio Celery

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

线程是什么?

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

在Python怎么定义线程?

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

import threadingimport time# 用于实例化线程目标函数def function(i): time.sleep(2) print('Thread {} is running.'.format(i)) time.sleep(2) returnfor i in range(5): # Python模块threading.Thread方法 t = threading.Thread(target=function, args=(i, )) t.start()

运行截图如下:

通过以上程序我们看出,定义好我们需要运行的目标函数来实例化线程,然后传入参数target即函数名,然后如果需要运行的目标函数有参数需要传递的话即可传入args元组,注意此处传入的是元组tuple。

然后我们在调用start()方法后启动实例化的线程

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

import threadingimport timeclass 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) returnfor i in range(1, 6): t = myThread(i) t.start()

运行截图如下:

通过上面的程序我们可以看出,我们需要定义新的Thread类的子类,并且通过重写__init__方法来传递参数,然后重写run()方法来实现目标函数,那么当我们创建出新的子类后就可以实例化该子类并通过start()方法来启动线程。

守护线程 setDaemon(True)

接下来我们在运行一段代码:

import threadingimport timeclass 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) returnprint('Mian THread starting')for i in range(1, 6): t = myThread(i) t.start() print('Mian THread end')

运行截图如下:

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

import threadingimport timeclass 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) returnprint('Mian THread starting')for i in range(1, 6): t = myThread(i) t.setDaemon(True) t.start() print('Mian THread end')

运行截图如下:

我们可以在运行截图中看到,当我们使用setDaemon(True)方法,设置子线程为守护线程时,主线程一旦执行结束,则全部线程全部被终止执行,可能出现的情况就是,子线程的任务还没有完全执行结束,就被迫停止。

那么我们能不能让主线程等等我们的子线程,等待子线程运行结束后,主线程再终止呢,即实现守护线程相反的效果,答案是可以得。

阻塞线程 join()

import threadingimport timeclass 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) returnprint('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()所完成的工作就是线程同步,即主线程任务结束之后,进入阻塞状态,一直等待其他的子线程执行结束之后,主线程再终止。

标签: #python子线程和主线程的关系