社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  Python

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

若数 • 6 年前 • 440 次点击  
阅读 16

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

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

关键词: threading multiprocessing asyncio Celery


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

线程是什么?

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

在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')
复制代码

运行截图如下:

运行截图
我们可以在运行截图中看到,当我们使用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()所完成的工作就是线程同步,即主线程任务结束之后,进入阻塞状态,一直等待其他的子线程执行结束之后,主线程再终止。

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/31322
 
440 次点击