Python开发技术—进程和线程1(第1关:求素数的个数 + 第2关:求合数的个数 + 第3关:交替打印foobarpython)

news/2025/2/12 4:00:25/

目录

第1关:求素数的个数

第2关:求合数的个数

 第3关:交替打印foobarpython

关于第一第二题思考:

(一)起始数字+结束数字 如何判断?

(二)main函数执行的代码功能

(三)光轮老师提出的素数优化代码:

 关于第三题思考:

(一)Await作用

(二)关于锁的机制和作用

第1关:求素数的个数

import math
from multiprocessing import cpu_count
from multiprocessing import Pool
'''使用python多进程  求区间[1,n]里 素数个数'''def isPrime(n):# 判断数字是否为素数#        请在此处添加代码       ## *************begin************#if n<=1:return 0if n==2:return 1if n % 2 ==0: #毛:注意此行必写,否则没有考虑到2这个数,循环从3开始,忽略了2return 0for i in range(3, int(math.sqrt(n)) + 1,2):if n%i == 0:return 0return 1# **************end*************#def howMany(T):# 计算给定区间含有多少个素数#        请在此处添加代码       ## *************begin************#sum = 0for i in range(T[0],T[1]+1):if isPrime(i):sum+=1return sum # **************end*************#def separateNum(N, CPU_COUNT):# 将整个数字空间N分成CPU_COUNT个部分#        请在此处添加代码       ## *************begin************##使用列表推导式生成一个二维列表list#每个子列包含CPU_COUNT个子列表,每个子列表包含2个元素:#起始数字:i*(N//CPU_COUNT)+1#结束数字:(i+1)*(N//CPU_COUNT)list = [[i * (N//CPU_COUNT)+1, (i+1)*(N // CPU_COUNT)] for i in range(0,CPU_COUNT)]list[0][0] =1if list[CPU_COUNT - 1][1] <N:list[CPU_COUNT - 1][1] = Nreturn list # **************end*************#
if __name__ == '__main__':N = int(input()) #输入一个整数N(区间[1,N]中的素数个数)CPU_COUNT = cpu_count()  #获取当前计算机CPU内核数 本机为8,存储在CPU_COUNT中pool = Pool(CPU_COUNT) #创建一个进程池,使用CPU_COUNT个进程sepList = separateNum(N, CPU_COUNT) #区间[1,N]分成CPU_COUNT个部分,存储在列表seqList中result = []#创建空列表result,存储异步任务结果for i in range(CPU_COUNT):result.append(pool.apply_async(howMany, (sepList[i], ))) #启动异步进程,计算个数,存储列表中pool.close()#关闭进程池,等待所有进程执行完毕pool.join() #使用列表推导式将result列表中的结果提取出来,存储在列表list中list = [res.get() for res in result]print(sum(list), end = '')#计算素数和,输出

素数优化:设置从3开始,步长为2 ,进行优化

第2关:求合数的个数

import threading
import math
ans = 0
lock = threading.Lock()def isPrime(n):# 判断数字是否为素数global ansif n <= 1:return Falsefor i in range(2, int(math.sqrt(n)) + 1):if n % i == 0:return Falsereturn Truedef howMany(T):# 计算给定区间含有多少个素数sum = 0for i in range(T[0], T[1] + 1):if isPrime(i):sum += 1lock.acquire()try:global ansans += sumfinally:lock.release()def seprateNum(N, CPU_COUNT):# 对整个数字空间N进行分段CPU_COUNTlist = [[i * (N // CPU_COUNT) + 1, (i + 1) * (N // CPU_COUNT)] for i in range(0, CPU_COUNT)]list[0][0] = 1if list[CPU_COUNT - 1][1] < N:list[CPU_COUNT - 1][1] = Nreturn listif __name__ == '__main__': #当前脚本是主程序N = int(input()) #获取用户输入的整数,转化为整型,赋值给变量NthreadNum = 32 #线程数设为32# *************begin************#t = [] #定义一个线程列表tsepList = seprateNum(N,threadNum)#将整数N划分为threadNum个部分for i in range(0,threadNum): #生成线程,存储在列表t中t.append(threading.Thread(target = howMany,args = (sepList[i],))) #将函数howmany作为线程的执行函数,传入sepList[i]中作为参数t[i].start() #启动线程for i in range(0,threadNum): #等所有线程执行结束t[i].join()print(N-1-ans,end='') #计算ans的值,将N-1-ans的值输出,不换行#ans:满足要求的数的个数,剩余数个数# **************end*************#

 

 第3关:交替打印foobarpython

import threading
import sys
import timedef showfoo(n):''':param n: 要输出foobarpython的次数:return: 无返回,可直接输出'''# *************begin************##注意缩进:这个for空4个格子for i in range(n): #循环n次lockpython.acquire() #获取锁,保证线程同步,锁名为:lockpythonprint('foo',end='') #输出'foo',确保不换行sys.stdout.flush() #刷新输出缓存lockfoo.release() #释放锁(保证线程同步),锁名为lockfootime.sleep(0.2) #线程休眠0.2S# **************end*************#def showbar(n):''':param n: 要输出foobarpython的次数:return: 无返回,可直接输出'''
# *************begin************#for i in range(n):lockfoo.acquire()print('bar',end='')sys.stdout.flush()lockbar.release()time.sleep(0.2)
# **************end*************#def showpython(n):''':param n: 要输出foobarpython的次数:return: 无返回,可直接输出'''# 请在此处添加代码       #
# *************begin************#for i in range(n):lockbar.acquire()print('python',end='')sys.stdout.flush()lockpython.release()time.sleep(0.2)
# **************end*************#if __name__ == '__main__':lockfoo = threading.Lock()  # 定义3个互斥锁lockbar = threading.Lock()lockpython =threading.Lock()n = int(input())t1 = threading.Thread(target=showfoo,args=[n])  # 定义3个线程t2 = threading.Thread(target=showbar,args=[n])t3 = threading.Thread(target=showpython,args=[n])lockfoo.acquire()  # 先锁住foo,bar锁,保证先打印foolockbar.acquire()#lockpython.acquire()t1.start()t2.start()t3.start()

 

关于第一第二题思考:

(一)起始数字+结束数字 如何判断?

i代表当前正在处理的部分的索引,从0到CPU_COUNT-1。在每个循环中,我们使用i计算当前部分的起始数字和结束数字,具体地:

起始数字:i * (N // CPU_COUNT) + 1,这是因为第一个部分的起始数字应该是1,而每个部分包含的数字个数是N // CPU_COUNT,因此第i个部分的起始数字应该是(i * (N // CPU_COUNT)) + 1。

结束数字:(i + 1) * (N // CPU_COUNT),这是因为第i个部分的结束数字应该比起始数字多包含(N // CPU_COUNT)个数字,而第(i+1)个部分的起始数字应该是第i个部分的结束数字+1,因此第i个部分的结束数字应该是(i+1) * (N // CPU_COUNT) - 1 + 1,即(i+1) * (N // CPU_COUNT)。

举个例子,如果N=100,CPU_COUNT=4,那么我们要将数字1~100分为4个部分,每个部分包含的数字个数是25。

对于第0个部分,其起始数字为0 * 25 + 1 = 1,结束数字为(0+1) * 25 = 25。

对于第1个部分,其起始数字为1 * 25 + 1 = 26,结束数字为(1+1) * 25 = 50。

对于第2个部分,其起始数字为2 * 25 + 1 = 51,结束数字为(2+1) * 25 = 75。

对于第3个部分,其起始数字为3 * 25 + 1 = 76,结束数字为(3+1) * 25 = 100。

因此,二维列表list的每个子列表都包含了一个部分的起始数字和结束数字。

(二)main函数执行的代码功能

首先判断当前文件是否作为主程序运行,如果是则执行下面的代码,如果不是则不执行。

1、输入一个整数N,表示要求区间[1,N]中的素数个数。

2、获取当前计算机的CPU核心数,存储在变量CPU_COUNT中。

3、创建一个进程池对象pool,使用CPU_COUNT个进程。

4、将区间[1,N]分成CPU_COUNT个部分,存储在列表sepList中。

5、创建一个空列表result,用于存储异步任务的结果。

使用pool.apply_async()方法对每个子区间sepList[i]启动一个异步进程,计算该区间内的素数个数,并将结果存储在result列表中。

6、关闭进程池,等待所有进程执行完毕。

使用列表推导式将result列表中的结果提取出来,存储在列表list中。

计算所有子区间内的素数个数之和,将结果输出。

三)光轮老师提出的素数优化代码:

 

 关于第三题思考:

(一)Await作用

await 操作符用于等待一个 Promise 兑现并获取它兑现之后的值。它只能在异步函数或者模块顶层中使用。

(二)关于锁的机制和作用:

我们需要控制三个线程的执行顺序,保证每个线程在执行一次后,只有另外一个线程才能开始执行。所以我们需要使用锁机制来实现线程同步。

在showfoo函数中,我们需要保证先打印’foo’,因此在函数开始时,先使用lockpython.acquire()来锁住python,保证showpython函数不会先执行。然后在打印完’foo’后,使用lockfoo.release()来释放foo锁,让showbar函数可以执行。

在showbar函数中,我们需要保证先打印’bar’,因此在函数开始时,先使用lockfoo.acquire()来锁住foo,保证showfoo函数已经执行完毕。然后在打印完’bar’后,使用lockbar.release()来释放bar锁,让showpython函数可以执行。

在showpython函数中,我们需要保证先打印’python’,因此在函数开始时,先使用lockbar.acquire()来锁住bar,保证showbar函数已经执行完毕。然后在打印完’python’后,使用lockpython.release()来释放python锁,让showfoo函数可以执行。

这三个锁的作用就是控制三个函数的执行顺序,保证每个函数执行一次后,只有另外一个函数才能执行。


http://www.ppmy.cn/news/39585.html

相关文章

使用串口重定向为服务器安装linux操作系统

在不借助显卡,通过串口来完成安装过程中的配置等选项。总结整个流程如下,方法很简单。在信创x86的设备上所使用的是redhat 7.4以及kylinOS的操作系统,串口工具是secureCRT。 首先进入Bios将串口重定向打开,并选择boot management,进入安装盘的启动界面 然后在启动界面的…

全国青少年信息素养大赛2023年python·选做题模拟五卷

目录 下载打印文档做题: 全国青少年电子信息智能创新大赛 python选做题模拟五卷 一、单选题 1. 对于数列3,8,11,15,17,19,25,30,44,采用“二分查找”法查找8,需要查找多少次?( ) A、5

Javase学习文档------面象对象初探

引入面向对象 面向对象的由来: 面向对象编程&#xff08;Object-Oriented Programming, OOP&#xff09;是一种编程范型&#xff0c;其由来可以追溯到20世纪60年代。在此之前&#xff0c;主流编程语言采用的是“过程化编程”模式&#xff0c;即面向过程编程模式。在这种模式下&…

Matlab与ROS(1/2)---服务端和客户端数据通信(五)

0. 简介 在前几讲我们讲了Matlab中的Message以及Topic的相关知识。而ROS主要支持的通信机制还有服务这一类。服务通过允许请求以及响应的通信方式&#xff0c;来给整个系统完成更紧密的耦合。服务客户端向服务服务器发送请求消息并等待响应。服务器将使用请求中的数据构造响应…

帮小忙(网站)

首先&#xff0c;网站的工具超级丰富&#xff0c;涵盖面好广&#xff0c;包含有图片类工具&#xff0c;数据换算&#xff0c;生活娱乐&#xff0c;教育&#xff0c;文本工具&#xff0c;开发工具&#xff0c;文档转换&#xff0c;视频&#xff0c;PDF转换工具等等9个大类&#…

SpringBoot创建和使用

目录 什么是SpringBoot SpringBoot的优点 SpringBoot项目的创建 1、使用idea创建 2、项目目录介绍和运行 Spring Boot配置文件 1、配置文件 2、配置文件的格式 3、properties 3.1、properties基本语法 3.2、读取配置文件 3.3、缺点 4、yml 4.1、优点 4.2、yml基本…

研究的艺术 (The craft of research) 读书笔记

前言 如果你对这篇文章感兴趣&#xff0c;可以点击「【访客必读 - 指引页】一文囊括主页内所有高质量博客」&#xff0c;查看完整博客分类与对应链接。 对于研究者而言&#xff0c;写作是一件很重要的事&#xff0c;好的写作不仅能让更多人愿意读&#xff0c;获得更大影响力&…

lodash-es 工具库

数字化管理平台 Vue3ViteVueRouterPiniaAxiosElementPlus Vue权限系统案例 个人博客地址 Lodash中文文档 Lodash 是一个一致性、模块化、高性能的 JavaScript 实用工具库&#xff0c;算是从 Underscore 分离出来的超集。 Lodash 通过降低 array、number、objects、string 等…