python之线程

1、线程理论

1.1、什么是线程
顾名思义,就是一条流水线工作的过程,一条流水线必须属于一个车间,一个车间的工作过程是一个进程
所以,进程只是用来把资源集中到一起(进程只是一个资源单位,或者说资源集合),而线程才是cpu上的执行单位。
多线程(即多个控制线程)的概念是,在一个进程中存在多个控制线程,多个控制线程共享该进程的地址空间,相当于一个车间内有多条流水线,都共用一个车间的资源。(一个进程里面开多个线程(共享同一个进程里面的内存空间))

注意:
1、所以进程里面真正干活的是线程(进程里面有线程)
2、进程只是用来把资源互相隔离开,而线程才是真正负责cpu来调用的
1.2、线程的创建开销小
创建进程的开销要远大于线程
如果我们的软件是一个工厂,该工厂有多条流水线,流水线工作需要电源,电源只有一个即cpu(单核cpu)
一个车间就是一个进程,一个车间至少一条流水线(一个进程至少一个线程)
创建一个进程,就是创建一个车间(申请空间,在该空间内建至少一条流水线)
而建线程,就只是在一个车间内造一条流水线,无需申请空间,所以创建开销小
1.3、线程与进程的区别
1、创建线程比进程开销小(开一个进程,里面就有空间了,而线程在进程里面,就没必要在开一个空间了)
2、多线程一定是在一个进程里面开启的,共享进程里面的资源
3、线程启动的速度快
4、同一进程下的多个线程共享进程的资源,而多个进程之间内存空间是隔离的
n = 100
def work():
	global n
	n-=100
如果开进程n是相互独立的,而线程是共享了资源,就不隔离了

在wins下开进程,子进程不会拷贝父进程的
在linux下开进程,子进程会完全拷贝父进程的

5、线程可以跟它所在的进程之内的线程通信
1.4、为何要用多线程
1. 多线程共享一个进程的地址空间
2. 线程比进程更轻量级,线程比进程更容易创建可撤销,在许多操作系统中,创建一个线程比创建一个进程要快10-100倍,在有大量线程需要动态和快速修改时,这一特性很有用
3. 若多个线程都是cpu密集型的,那么并不能获得性能上的增强,但是如果存在大量的计算和大量的I/O处理,拥有多个线程允许这些活动彼此重叠运行,从而会加快程序执行的速度
4. 在多cpu系统中,为了最大限度的利用多核,可以开启多个线程,比开进程开销要小的多(这一条并不适用于python)

2、线程

2.1、threading模块
threading模块和multiprocessing模块在使用层面,有很大的相似性
2.2、开启线程的两种方式
2.2.1、方式一
from threading import Thread
import time

def task(n, name):
    print('{} is running'.format(name))
    time.sleep(n)
    print('{} is done'.format(name))

if __name__ == '__main__':
    obj1 = Thread(target=task, args=(3, '线程1'))
    obj2 = Thread(target=task, args=(5, '线程2'))
    obj1.start()
    obj2.start()
    obj1.join()  # 等待子线程obj1执行完成
    obj2.join()  # 等待子线程obj2执行完成
    print('主')
2.2.2、方式二
from threading import Thread
import time

class Mytask(Thread):
    def __init__(self, n, name):
        super().__init__()
        self.n = n
        self.name = name

    def run(self) -> None:
        print('{} is running'.format(self.name))
        time.sleep(self.n)
        print('{} is done'.format(self.name))

if __name__ == '__main__':
    obj1 = Mytask(3, '线程1')
    obj2 = Mytask(5, '线程2')
    obj1.start()
    obj2.start()
    obj1.join()
    obj2.join()
    print('主')
2.3、同一个进程下的多个线程数据共享
from threading import Thread

money = 10

def task(n):
    global money
    money = n

if __name__ == '__main__':
    t = Thread(target=task, args=(66,))
    t.start()
    t1 = Thread(target=task, args=(88,))
    t1.start()
    t.join()
    t1.join()
    print('主线程里的money: {}'.format(money))  # 88
2.4、线程对象的其他属性和方法
from threading import Thread, active_count, current_thread
import time, os

def task():
    print(current_thread().name)  # 线程名字
    print('开始运行')
    print('进程是: {}'.format(os.getpid()))
    time.sleep(3)
    print('运行结束')

if __name__ == '__main__':
    t = Thread(target=task, name='线程1')
    t.start()
    t1 = Thread(target=task, name='线程2')
    t1.start()
    print(t.is_alive())  # 判断线程是否存活
    print(t1.is_alive())  # 判断线程是否存活
    print(t.ident)  # 当作线程id号
    print(t1.ident)  # 当作线程id号
    print(active_count())  # 打印出3,开了2个线程,还有1个是主线程
    print('main进程是: {}'.format(os.getpid()))

总结:
getName(): 返回线程名
setName(): 设置线程名
is_alive(): 返回线程是否存活
ident: 当作是线程id号
active_count: 当前进程下有几个线程存活

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

def task(n):
    print('运行开始')
    time.sleep(n)
    print('运行结束')

if __name__ == '__main__':
    t = Thread(target=task, args=(3,))
    t1 = Thread(target=task, args=(6,))
    t.daemon = True  # 等价于t.setDaemon(True)
    t.start()
    t1.start()
    print('主')
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值