Python系列之多线程

1、线程理论

  • 在传统操作系统中,每个进程有一个地址空间,而且默认就有一个控制线程

  • 线程顾名思义,就是一条流水线工作的过程(流水线的工作需要电源,电源就相当于cpu),而一条流水线必须属于一个车间,一个车间的工作过程是一个进程,车间负责把资源整合到一起,是一个资源单位,而一个车间内至少有一条流水线。所以,进程只是用来把资源集中到一起(进程只是一个资源单位,或者说资源集合),而线程才是cpu上的执行单位。

  • 多线程(即多个控制线程)的概念是,在一个进程中存在多个线程,多个线程共享该进程的地址空间,相当于一个车间内有多条流水线,都共用一个车间的资源。例如,北京地铁与上海地铁是不同的进程,而北京地铁里的13号线是一个线程,北京地铁所有的线路共享北京地铁所有的资源,比如所有的乘客可以被所有线路拉。

2、线程实践

  • 开启线程的两种方式

①:方式一

from threading import Thread
import time

def sayhi(name):
    time.sleep(2)
    print('%s say hello' %name)

if __name__ == '__main__':
    t=Thread(target=sayhi,args=('egon',))
    t.start()
    print('主线程')

②:方式二

#方式二
from threading import Thread
import time

class Sayhi(Thread):
    def __init__(self,name):
        super().__init__()
        self.name=name
    def run(self):
        time.sleep(2)
        print('%s say hello' % self.name)

if __name__ == '__main__':
    t = Sayhi('egon')
    t.start()
    print('主线程')

线程与进程的区别

  • 谁的开启速度快?

1、在主进程下开启线程

from threading import Thread

def work():
    print('hello')

if __name__ == '__main__':
    t=Thread(target=work)
    t.start()
    print('主线程/主进程')

执行结果如下,几乎是t.start ()的同时就将线程开启了,然后先打印出了hello,证明线程的创建开销极小

hello
主线程/主进程

2、在主进程下开启子进程

from multiprocessing import Process

def work():
    print('hello')

if __name__ == '__main__':
    #在主进程下开启子进程
    p=Process(target=work)
    p.start()
    print('主线程/主进程')

执行结果如下,p.start ()将开启进程的信号发给操作系统后,操作系统要申请内存空间,让好拷贝父进程地址空间到子进程,开销远大于线程

主线程/主进程
hello
  • 瞅一瞅pid?

1、在主进程下开启多个线程,每个线程都跟主进程的pid一样

from threading import Thread
import os

def work():
    print('hello',os.getpid())

if __name__ == '__main__':
    t1=Thread(target=work)
    t2=Thread(target=work)
    t1.start()
    t2.start()
    print('主线程/主进程pid',os.getpid())

执行结果

hello 7939
hello 7939
主线程/主进程 7939

2、开多个进程,每个进程都有不同的pid

from multiprocessing import Process
import os

def work():
    print('hello',os.getpid())

if __name__ == '__main__':
    p1=Process(target=work)
    p2=Process(target=work)
    p1.start()
    p2.start()
    print('主线程/主进程',os.getpid())

执行结果

主线程/主进程 7951
hello 7952
hello 7953
  • 同一进程内的线程共享该进程的数据?

1、进程之间地址空间是隔离的


from multiprocessing import Process
import os

def work():
    global n
    n=0

if __name__ == '__main__':
    n=100
    p=Process(target=work)
    p.start()
    p.join()
    print('主',n)

执行结果如下,毫无疑问子进程p已经将自己的全局的n改成了0,但改的仅仅是它自己的,查看父进程的n仍然为100

主 100

2、同一进程内开启的多个线程是共享该进程地址空间的

from threading import Thread
import os

def work():
    global n
    n=0

if __name__ == '__main__':
    n=100
    t=Thread(target=work)
    t.start()
    t.join()
    print('主',n)

执行结果如下, 查看结果为0,因为同一进程内的线程之间共享进程内的数据

主 0

Thread的其他属性和方法

Thread实例对象的方法
# isAlive(): 返回线程是否活动的。
# getName(): 返回线程名。
# setName(): 设置线程名。

threading模块提供的一些方法:
# threading.currentThread(): 返回当前的线程变量。
# threading.enumerate(): 返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后的线程。
# threading.activeCount(): 返回正在运行的线程数量,与len(threading.enumerate())有相同的结果。

验证:

from threading import Thread
import threading
from multiprocessing import Process
import os

def work():
    import time
    time.sleep(3)
    print(threading.current_thread().getName())


if __name__ == '__main__':
    #在主进程下开启线程
    t=Thread(target=work)
    t.start()

    print(threading.current_thread().getName())
    print(threading.current_thread()) #主线程
    print(threading.enumerate()) #连同主线程在内有两个运行的线程
    print(threading.active_count())
    print('主线程/主进程')

守护线程

无论是进程还是线程,都遵循:守护xxx会等待主xxx运行完毕后被销毁

需要强调的是:运行完毕并非终止运行

1、对主进程来说,运行完毕指的是主进程代码运行完毕

2、对主线程来说,运行完毕指的是主线程所在的进程内所有非守护线程统统运行完毕,主线程才算运行完毕
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值