首页 > 编程语言 >python线程

python线程

时间:2022-10-26 18:44:13浏览次数:37  
标签:__ python put 线程 time print import

1、概念

cpu执行程序的最小单位,从属于进程,是程序的实际执行者。一个进程至少包含一个主线程,也可以有更多的子线程。Python可以运行多线程,但和单核CPU多进程一样,在给定时刻只有一个线程会执行。

2、一个进程资源包含多个线程

 

from threading import Thread
from multiprocessing import Process
import os,time,random

def func(num):    
    time.sleep(random.uniform(0.1,1))
    print("当前进程{},参数是{}".format(os.getpid(),num))
    

for i in range(10):
    t = Thread(target=func,args=(i,))
    t.start()
    
print(os.getpid())

 

3、并发的多线程比并发多进程速度快

def func(num):    
    print("当前进程{},参数是{}".format(os.getpid(),num))
    
if __name__ == "__main__":

    # 多线程
    lst = []
    # 记录开始时间
    startime = time.time()
    for i in range(1000):
        t = Thread(target=func,args=(i,))
        t.start()
        lst.append(t)
    
    # 等到所有的子线程执行完毕
    for i in lst:
        i.join()
    
    # 计算结束时间
    endtime = time.time()
    print("多线程执行时间",(endtime - startime)) # 0.18

    # 多进程
    lst = []
    # 记录开始时间
    startime = time.time()
    for i in range(1000):
        t = Process(target=func,args=(i,))
        t.start()
        lst.append(t)
    
    # 等到所有的子线程执行完毕
    for i in lst:
        i.join()
    
    # 计算结束时间
    endtime = time.time()
    print("多进程执行时间",(endtime - startime)) # 44.41

4、多线程之间共享同一份进程资源

num = 1000
def func():
    global num
    num -= 1
    
for i in range(1000):
    t = Thread(target=func)
    t.start()
    
print(num)

5、自定义线程

from threading import Thread
import os
import time


class MyThread(Thread):
    def __init__(self,name):
        # 手动调用父类的构造方法
        super().__init__()
        self.name = name
        
    def run(self):
        time.sleep(1)
        print("当前进程号码是{},名字是{}".format(os.getpid() , self.name))


if __name__ == "__main__":
    t = MyThread("当前是一个线程")
    t.start()
    print("主线程执行结束 ... ")

6、线程相关函数

线程.is_alive()    检测线程是否仍然存在
线程.setName()     设置线程名字
线程.getName()     获取线程名字
1.currentThread().ident 查看线程id号 
2.enumerate()        返回目前正在运行的线程列表
3.activeCount()      返回目前正在运行的线程数量

7、守护线程,等待所有线程全部执行完毕之后,自己在终止,守护所有线程

from threading import Thread
import time
def func1():
    while True:
        time.sleep(0.5)
        print("我是func1")

def func2():
    print("我是func2 start ... ")
    time.sleep(3)
    print("我是func2 end ... ")

def func3():
    print("我是func3 start ... ")
    time.sleep(5)
    print("我是func3 end ... ")

if __name__ == "__main__":
    t1 = Thread(target=func1)
    t2 = Thread(target=func2)
    t3 = Thread(target=func3)
    
    # 在start调用之前,设置线程为守护线程
    t1.setDaemon(True)
    
    t1.start()
    t2.start()
    t3.start()
    
    print("主线程执行结束 .... ")

8、线程安全问题

from threading import Lock,Thread
import time
n = 0

def func1(lock):
    global n    
    lock.acquire()
    for i in range(1000000):            
        n += 1
    lock.release()

def func2(lock):
    global n
    # with 自动完成上锁+解锁
    with lock:
        for i in range(1000000):        
            n -= 1
        
    
if __name__ == "__main__":
    lst = []
    lock = Lock()
    
    startime = time.time()
    for i in range(10):
        t1 = Thread(target= func1,args=(lock,))
        t2 = Thread(target= func2,args=(lock,))
        t1.start()
        t2.start()
        lst.append(t1)
        lst.append(t2)


    for i in lst:
        i.join()
    
    endtime = time.time()
    # 88.30 1.84
    print("主线程执行结束 ...  打印{} 时间是{}".format(n,endtime-startime))

9、信号量 Semaphore (线程)

from threading import Semaphore , Thread
import time
def func(i,sm):
    # 上锁 + 解锁
    with sm:
        print(i)
        time.sleep(3)    
if __name__ == "__main__":
    # 支持同一时间,5个线程上锁
    sm = Semaphore(5)
    for i in range(20):
        Thread(target=func,args=(i,sm)).start()
    
"""
再创建线程的时候是异步创建
在执行任务时,遇到Semaphore进行上锁,会变成同步程序
"""

10、死锁 互斥锁 递归锁

死锁分为语法和逻辑死锁,只上锁不解锁

递归锁专门用来解决这种死锁现象或临时用于快速解决线上项目发生阻塞死锁问题的

互斥锁(尽量用一把锁解决问题)

11、事件

from threading import Event,Thread
import time,random
"""
    e = Event()
    # wait   动态添加阻塞
    # clear  将内部的阻塞值改成False
    # set    将内部的阻塞值改成True
    # is_set 获取内部的阻塞值状态(True False)
"""
# 基本语法
e = Event()
print(e.is_set())
e.set()
print(e.is_set())
e.clear()
print(e.is_set())
# 代表最多阻塞3秒
e.wait(3)
print("程序运行中... ")

12、线程缺陷

python线程可以并发,但是不能并行,同一个进程下的多个线程不能分开被多个cpu同时执行。

原始是因为python自带gil全局锁,限制同一个时间,一个进城下多个线程只能被一个cpu执行,不能实现并行操作,python是解释性语言,执行一句编译一句,而不是一次性全部编译成功,不能提前规划,都是临时调度,容易造成cpu调度异常,所以加一把GIL全局锁,想要线程并行解决,使用多进程间接实现线程并行或使用jpython解释器

13、线程队列(相同数据类型)

from queue import Queue
"""
put 存
get 取
put_nowait 存,超出了队列长度,报错
get_nowait 取,没数据的时,直接报错
linux windows 线程中 put_nowait get_nowait 都支持
"""
# (1) Queue 
"""先进先出,后进后出"""
q = Queue()
q.put(1)
q.put(2)
print(q.get())
print(q.get())
# 取出不来,阻塞
# print(q.get())
# 没有数据时,报错
# print(q.get_nowait())

# 指定队列长度
q2 = Queue(3)
q2.put(100)
q2.put(101)
# q2.put(102)
# 存放的数据超出了队列长度,阻塞
# q2.put(103)
q2.put_nowait(104)

# (2)LifoQueue 先进后出,后进先出(栈的特点)
from queue import LifoQueue
lq = LifoQueue(3)
lq.put(11)
lq.put(22)
lq.put(33)
# lq.put_nowait(44) error

print(lq.get())
print(lq.get())
print(lq.get())
# print(lq.get()) 阻塞

# (3)PriorityQueue 按照优先级顺序进行排序(默认从小到大)
from queue import PriorityQueue
pq = PriorityQueue()
# 可以存放数字
# pq.put(80)
# pq.put(81)
# pq.put(18)

 14、线程池

# ThreadPoolExecutor 线程池的基本使用
from threading import current_thread  as cthread
def func(i):
    print("thread ... start" ,cthread().ident )
    print("thread ... end " , i)
    return cthread().ident
    

if __name__ == "__main__":
    lst = []
    setvar = set()
    # (1) 创建线程池对象
    """参数: 默认并发的线程数 是 os.cpu_count() * 5 = 40"""
    tp = ThreadPoolExecutor() 
    
    # (2) 异步提交任务
    """默认如果一个线程短时间内可以完成更多的任务,线程池就不会使用更多的线程来完成,以节省资源"""
    for i in range(100):
        res = tp.submit(func,10)
        lst.append(res)

    # (3) 获取返回值
    for i in lst:
        setvar.add(i.result())
        
    # (4) 等待所有子线程执行结束之后,在执行主线程
    # tp.shutdown()
    print("主线程执行结束 .... ")
    print(setvar , len(setvar))
"""
无论是进程池还是线程池,都是由固定的进程数或者线程数来执行所有的任务.并不对额外创建多余的进程或者线程.
"""
# (3) 线程池 map
from collections import Iterator,Iterable
def func(i):
    # 同一时间5个线程执行任务
    print("thread ... " ,cthread().ident )
    return i * "*" 
    
if __name__ == "__main__":
    # 创建线程池对象(最大允许并发5个线程)
    tp = ThreadPoolExecutor(5)
    # 把执行的结果返回到迭代器中
    it = tp.map(func,range(20))
    # 判断返回值是迭代器
    print(isinstance(it,Iterator))
    # 等待所有子线程执行结束.
    tp.shutdown()
    # 遍历迭代器
    for i in it:
        print(i)

15、进程池

from concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor
import os,time

def func(i):
    print("任务执行中 ... start" , os.getpid())
    time.sleep(3)
    print("任务执行结束 ... end " , i)
    return i
#  ProcessPoolExecutor 进程池的基本使用

if __name__ == "__main__":
    lst = []
    # cpu逻辑核心数
    # print(os.cpu_count())
    # (1) 创建进程池对象
    """参数: 默认获取的是最大cpu逻辑核心数 8"""
    p = ProcessPoolExecutor(8)

    # (2) 异步提交任务
    """默认如果一个进程短时间内可以完成更多的任务,进程池就不会使用更多的进程来完成,以节省资源"""
    for i in range(10):
        res = p.submit(func,i)
        lst.append(res)
    
    # (3) 获取当前进程任务中的返回值(result在获取任务的返回值时,有阻塞)
    # for i in lst:
        # print(i.result())
    
    # (4) 等待所有子进程执行结束之后,在继续执行主进程内容(shutdown)
    p.shutdown()  # <=> join
    print("<=======>")
    print(os.getpid())

 

标签:__,python,put,线程,time,print,import
From: https://www.cnblogs.com/songyunjie/p/16829593.html

相关文章

  • 使用Python时常见的9个错误
    通过应用软件工程最佳实践,可以交付质量更好数据科学的项目。更好的质量可能是更少的错误、可靠的结果和更高的编码效率。最佳实践都是从错误中总结出来的,所以这里我们总结了......
  • Python代码编写辅导:CSC411 Digit Classification
    全文链接:tecdat.cn/?p=29674RequirementInthisassignment,youwillcomparethecharacteristicsandperformanceofdifferentclassifiers,namelylogisticregre......
  • python进程
    1、进程概念进程是一个执行中的程序,资源分配的最小单位。每个进程都拥有自己的地址空间、内存、数据栈以及其他用于跟踪执行的辅助数据。在单核CPU系统中的多进程,内存中可......
  • Python基础21
    今日内容概要第三方模块的下载与使用网络爬虫模块值requests模块网络爬虫实战之爬取链家二手房数据自动化办公领域之openpyxl模块今日内容详细第三方模块的下载与......
  • 转 python 自动监控表空间,并自动添加数据文件
    侯志清-江西南昌 python自动监控表空间,并自动添加数据文件#!/usr/bin/pythonimportosimporttimeimportlinecache#定义记录日志文件defrlog(log)......
  • python进程
    1、概念进程是一个执行中的程序,资源分配的最小单位。每个进程都拥有自己的地址空间、内存、数据栈以及其他用于跟踪执行的辅助数据。在单核CPU系统中的多进程,内存中可以有......
  • Java查询服务器(windows + linux)和系统各个指标数据 cpu、内存、硬盘、线程、请求错
    importjava.io.BufferedReader;importjava.io.File;importjava.io.IOException;importjava.io.InputStreamReader;importjava.lang.management.ManagementFactory......
  • python切片数组越界?
    1.在对list进行切片时,如x[9:12],若len(x)=10,只会返回x[9],而不会像其他语言直接数组越界错误。x=[iforiinrange(10)]print(x)foriinrange(0,10,3):print(x[i:i+3]......
  • 图像处理:opencv-python给图像加文字
    1.起因计算机视觉中常常会需要在图片上加文字,这样可以增强图像数据的可读性。2.工具opencv-python3.方法importmatplotlib.pyplotaspltfromPILimportImag......
  • python3 使用位图排序
    代码frombitmapimportBitMapa=[1,5,3,4,7,8,15,6,9]print(a)bm=BitMap(max(a))#print(dir(bm))print(bm.tostring())foriina:bm.set(i)print(bm......