多线程--

线程概述

进程是cpu资源分配的最小单位,线程是cpu调度的最小单位。
线程必须依托进程存在,同时一个进程内可能含有多个线程,但至少含有一个线程。这个线程叫做主线程!


内核---2个 能跑两个进程 
一个进程至少包括一个线程。这个线程叫做主线程
逻辑处理器----4个 就意味着 运用超线程处理技术 可以同时跑4个线程

线程不拥有独立的资源,同一进程内的线程共享同一地址空间(系统资源)

同一个进程中可以包括多个线程,并且线程共享整个进程的资(寄存器、堆、栈、上下文),一个进程至少包括一个线程
一个进程至少包括一个线程。这个线程叫做主线程

子线程

def sing():
    for i in range(4):
        print('sing')

def dance():
    for i in range(4):
        print('dance...')

if __name__ == '__main__':
    sing()
    dance()


# 很显然刚刚的程序并没有完成唱歌和跳舞同时进行的要求
#如果想要实现“唱歌跳舞”同时进行,那么就需要一个新的方法,叫做:多任务 也就是多线程


#线程(英语:thread)是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。

#在线看视频:其实是一边从网上下载一边用播放器播放,从进程来讲就一个(咱们打开的网页),其中下载由一个线程管理,播放由一个线程管理,多线程要导入模块


import threading,time

def sing():
    for i in range(4):
        print('sing...')
        time.sleep(3)
        print('唱歌结束')

def dance():
    for i in range(4):
        print('dance...')
        time.sleep(3)
        print('跳舞结束')

if __name__ == '__main__':
    f_sing = threading.Thread(target=sing,name='fufu')
    f_dance = threading.Thread(target=dance,name='jianqi')

    print(f_sing.getName())
    f_sing.setName('jianqi')
    print(f_sing.getName())

    f_sing.setDaemon(True)   #设置守护进程,主线程结束后子线程会关闭
    f_dance.setDaemon(True)  #设置守护进程,主线程结束后子线程会关闭

    f_sing.start()   #启动
    f_dance.start()  #启动

    #f_dance.join()       #阻塞,子线程执行完才会开始执行下面的代码
    #f_sing.join()        #阻塞,子线程执行完才会开始执行下面的代码

    print('主线程执行完成')

#我们在使用start()这个方法的时候 其实内部调用的run方法

# run方法演示
import time
from threading import Thread

class Myjq(Thread):
    def run(self) -> None:
        print('hello')
        time.sleep(3)
    print('bye')

jq = Myjq()
jq.start()

#传参
import time
from threading import Thread

class Myjq(Thread):
    def __init__(self,name):  #*args,**kwargs
        super().__init__()    #*args,**kwargs
        self.name = name

    def run(self) -> None: #->None 可写可不写,本意是里面不需要传值
        print('hello{}'.format(self.name))
        time.sleep(3)
        print('bye')

jq = Myjq("fufu")
jq.start()

#需要继承  需要新的东西  要init 要super
#不继承    需要init
#完全继承   不要新的东西  不需要init

锁
from threading import Thread

a = 1
def f():
    global a
    a = 356

if __name__ == '__main__':
    print(a)
    t = Thread(target=f)
    t.start()
    t.join()
    print(a)

这个问题就会涉及到资源的掠夺
from threading import Thread,Lock

a = 1
def f():
    global a
    lock.acquire()   #获取锁
    for i in range(1000000):
        a += 1
    lock.release()   #释放锁

def f1():
    global a
    lock.acquire()  # 获取锁
    for i in range(1000000):
        a -= 1
    lock.release()  # 释放锁

'''
a += 1
1 先拿到值
2 再进行赋值运算
'''

if __name__ == '__main__':
    lock = Lock()
    print(a)
    t1 = Thread(target=f)
    t2 = Thread(target=f1)
    t1.start()
    t2.start()
    t1.join()
    t2.join()
    print(a)

#死锁:两个线程分别占有一部分资源,并且同时都在等待对方的资源,等待的过程就叫死锁
#互斥锁,乐观锁,悲观锁
#GIL:全局解释锁,单核的情况下实现多任务-并发

'''
python的代码执行由python虚拟机(也叫解释器主循环,CPython版本)来控制,
python在设计之初就考虑到在解释器的主循环中,同时只有一个线程在运行。
即在任意时刻只有一个线程在解释器中运行。对python虚拟机访问的控制由全局解释锁GIL控制,
正是这个锁来控制同一时刻只有一个线程能够运行。
'''

队列

#创建队列(可以指定长度)
from random import randint
from queue import Queue
from threading import Thread

my_q = Queue(10)   #容量  队列大小
def f(my_que):
    for i in range(10):
        num = randint(0,1000)
        my_que.put(num) #放任务

def f1(my_que):
    for j in range(5):
        num = my_que.get()
        print(num)  #取任务

t1 = Thread(target=f,args=(my_q,))
t2 = Thread(target=f1,args=(my_q,))
t1.start()
t2.start()
t1.join()
t2.join()

my_q.qsize()  #查看队列里还剩多少个
-------------------------------------------------------------------------------------------
my.put(1)
print(my.qsize())
my.get()
print(my.qsize())
print(my.empty())  #是否为空
print(my.full())   #是否为满

-------------------------------------------------------------------------------------------
put 是一个任务
my_q.task_done()
队列.join()
主要是给join用的,每次get后需要调用task_done,直到所有任务都task_done.join才取消阻寒
如果线程里每从队列里取一次,但没有执行task_done(),则join无法判断队列到底有没有结束,在最后执行个join()是等不到结果的,会一直挂起。可以理解为,每task_done一次 就从队列里翻掉一个元素,这样在最后join的时候根据队列长度是否为零来判断队列是否结束,从而执行主线程。

my_q.task_done()已默认调用
-----------------------------------------------------------------------------------------
生产者  消费者模式
一个只负责生产  一个只负责消费 实现解耦 高内聚低耦合
阿帕奇 Apache是世界使用排名第一的web服务器软件
恩即克斯 nginx 是一个高性能的HTTP和反向代理web服务器
IIS服务器个称为:Internet Information Services。是微软旗下的web股务器
平衡生产力 和消费力

线程池

概述

更好的利用多线程 出现池 从而提高利用率 可以方便的管理线程,也可以减少内存的消耗。

线程池
线程池,通过有限的几个同定线程为大量的操作服务,减少了创建和销毁线程所需的时间,从而提高效率。
如果一个线程的时间非常长,就没必要用线程池了(不是不能作长时间操作,而是不宜。),况且我们还不能控制线程池中线程的开始、挂起、和中止。

from queue import Queue
from threading import Thread
import time

class TheradPool(object):
    '''
    创建指定数量的线程池
    '''
    def __init__(self,n): #线程的数量
        self.q = Queue()  #放任务的队列
        for i in range(n):
            Thread(target=self.worker,daemon=True).start()  #开始线程
                    #指向方法    函数名  设置守护进程

    def worker(self): #取任务来执行 不需要参数
        while True: #一直循环
            func = self.q.get()  #取任务
            func()  #执行函数
            self.q.task_done()  #执行完毕

    def put_q(self,func): #放任务
        '''
        向对象加入要执行的任务函数
        '''
        self.q.put(func)

    def join_q(self):
        self.q.join() #阻塞等待任务完成

def task1(): #任务1
    print('1go...')
    time.sleep(3)
    print('lend')

def task2(): #任务2
    print('2go...')
    time.sleep(3)
    print('2end')

def task3(): #任务3
    print('3go...')
    time.sleep(3)
    print('3end')

if __name__ == '__main__':
    pool = TheradPool(3)  #创建两个线程  进入阻塞   等待任务
    pool.put_q(task1())   #发布任务
    pool.put_q(task2())   #发布任务
    pool.put_q(task3())
    print("放任务完成")
    pool.join_q()         #阻塞
    print('任务执行完毕')

如果去掉守护进程 他就会卡在 get()标志着 子线程任务执行不完,
子线程没完成  主线程一直等子线程完成
join 只有在队列不为空时才会阻塞

带参数的线程池

from queue import Queue
from threading import Thread
import time

class TheradPool(object):
    '''
    创建指定数量的线程池
    '''
    def __init__(self,n): #线程的数量
        self.q = Queue()  #放任务的队列
        for i in range(n):
            Thread(target=self.worker,daemon=True).start()  #开始线程
                    #指向方法    函数名  设置守护进程

    def worker(self): #取任务来执行 不需要参数
        while True: #一直循环
            func,args,kwargs = self.q.get()  #取任务
            func(*args,**kwargs)  #执行函数
            self.q.task_done()  #执行完毕

    def put_q(self,func,*args,**kwargs): #放任务
        '''
        向对象加入要执行的任务函数
        '''
        self.q.put((func,args,kwargs)) #变成元组

    def join_q(self):
        self.q.join() #阻塞等待任务完成

def task1(*args,**kwargs): #任务1
    print('1go...')
    print(args)
    print(kwargs)
    time.sleep(3)
    print('lend')

def task2(): #任务2
    print('2go...')
    time.sleep(3)
    print('2end')

def task3(): #任务3
    print('3go...')
    time.sleep(3)
    print('3end')

if __name__ == '__main__':
    pool = TheradPool(3)
    pool.put_q(task1,2,3,4,a = 'hello',b = 'world')
    pool.put_q(task2)
    pool.put_q(task3)
    print("放任务完成")
    pool.join_q()  #阻塞
    print('任务执行完毕')

内置线程池

评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值