python之进程和线程(一)

概念解释

	说到进程和线程就要引用我们下面三个点:
	1.多任务
	如果是单核CPU的情况下,比方说我们一边开着音乐,一边开着浏览器,再打着游戏
	这个时候我们的CPU不是同事执行这个任务,而是来回快速切换,因为我们的CPU处理
	速度是很快的,所以我们感觉不到,那四核CPU呢,如果执行八个任务,这样也是来回切换
	,但是我们切换的时间轮更少了,8个任务之间快速来调度,效率也更高了。
	2.多进程
	操作系统分配资源的最小单位。一个线程只能属于一个进程,而一个进程可以有多个线程,但至少有一个线程
	3.多线程
	线程是进程中的最小执行单位,它可与同属一个进程的其它线程共享进程所拥有的全部资源
	同一进程中的多个线程之间可以并发执行

构造子进程

	from multiprocessing import Process  #用multiprocessing可以在主进程中创建子进程
	import os   #导入os模块
	def mk_pro(name):
	    print('子进程{},id是{}'.format(name,os.getpid()))     #os.getpid():查看进程id
	if __name__ == '__main__':
	    print('父进程id是{}'.format(os.getpid()))
	    p = Process(target=mk_pro,args=('test',))   #利用Process创建子进程实例,target传入函数,args传入函数参数
	    #args这里要注意,当元祖只有一个元素的时候要加上逗号,不要掉陷阱里面了
	    print('子进程启动')
	    p.daemon = True#将主线程设置为Daemon线程,它退出时,其它子线程会同时退出,不管是否执行完任务
	    daemon 默认会是False,为True则是它退出时,其它子线程会同时退出,不管是否执行完任务
	    p.start()   #启动进程
	    p.join()    #等待子进程结束后继续往下运行。用于进程间同步。
	    print('子进程结束')
	   这里需要注意的是:
		   #这里的父进程指得就是我们当前程序文件,如果不加if __name__ == '__main__':
           #则会报错,因为子进程在运行时是依赖于父进程的所有内容的,创建一个子进程的
           时候该子进程就会复制当前父进程的模块。
       不加会报如下错误:
       		RuntimeError: 
			        An attempt has been made to start a new process before the
			        current process has finished its bootstrapping phase.
			
			        This probably means that you are not using fork to start your
			        child processes and you have forgotten to use the proper idiom
			        in the main module:
			
			            if __name__ == '__main__':
			                freeze_support()
			                ...
			
			        The "freeze_support()" line can be omitted if the program
			        is not going to be frozen to produce an executable
			总结:
		    # 1. Process(target=run_proc, args=('test',)) 用于创建一个子进程,target指定子进程中任务,args给target指定的任务传参。
		    # 2. start()方法启动进程
		    # 3. join()方法等待子进程结束后继续往下运行。用于进程间同步。
		    # 4. Process(target=run_proc, args=('test',)daemon=True)
		    # daemon=True #将主线程设置为Daemon线程,它退出时,其它子线程会同时退出,不管是否执行完任务
		    #if __name__ == '__main__':
		    #这里的父进程指得就是我们当前程序文件,如果不加if __name__ == '__main__':
		    #则会报错,因为子进程在运行时是依赖于父进程的所有内容的,创建一个子进程的时候该子进程就会复制当前父进程的模块。

进程池

		概念解释:
		比方说一个快递公司有五个送货员,五个人都出去送货了,这时又来一车货
		这个时候怎么办呢,只有五个人,我们就只能等某一个送货员送完货回来之后
		再去送这新来的货物,在我们进程中也是一样,如果进程池序列中没有可供使
		用的进程,那么程序就会等待,直到进程池中有可用进程为止。
		首先也要导入我们的池对象Pool
		from multiprocessing import Process,Pool   #Pool:池对象
		def python_pool(num):
		    print(pow(num,10))
		if __name__ == '__main__':
		    pool = Pool(5)
		    for i in range(5):
		        pool.apply_async(python_pool,args=(i,))   #从进程池里取出一个进程并异步执行
		    pool.terminate()    #立刻关闭进程池
		    pool.close()   #等待所有进程结束才关闭线程池
		    pool.join()    #主进程等待所有子进程执行完毕,必须在close或terminete之后
		
		我们也可以用apply方法,那apply和apply_async到底有什么区别呢?
			apply方法是阻塞的。
			意思就是等待当前子进程执行完毕后,在执行下一个进程。
			apply_async 是异步非阻塞的。
		    意思就是:不用等待当前进程执行完毕,随时根据系统调度来进行进程切换。
		刚上面的代码中用到了apply_async这个方法,注释意思说是从进程池里取出一个进程
		并异步执行,又介绍了apply方法,反复提到异步同步
		这里要给大家解释一下同步和异步的概念:
			比方说两个人去餐厅吃饭,我们点好餐之后坐在那里等做好菜端上来
			这种叫做同步,点好之后我们去干别的事情,比如去买饮料、逛街
			这种叫异步,在进程池中也是这样的原理,同步是指一个进程在执行
			某个请求的时候,必须要到收到对方返回的信息才继续执行下去异步
			是指进程在执行某个请求时,不管其他的进程的状态,这个进程就
			执行后续操作;当有消息返回时系统会通知进程进行处理,这样可以提高执行的效率
			# 总结:
		    # 1. Pool(n) 产生大小为n的进程池。   Pool的默认大小是CPU的核数  cpu_count()
		    # 2. close()方法修改进程池状态为close,不允许再添加新的任务。
		    #    p.terminate()  # 杀死终止 所有的进程
		    # 3. join()方法父进程等待所有子进程执行完毕, 在join之前需调用close()方法 from multiprocessing import cpu_count
		    # 4. 使用p.apply(target=,args,kwargs)给进程池分配任务
		    # 5. p.apply_async是异步任务。python3中apply也是调用异步apply_async

线程

	 多任务可以由多进程完成,也可以由一个进程内的多线程完成。
	 刚刚我们讲到线程是进程的最小执行单元,一个进程至少有一个线程。
	 Python的标准库提供了两个模块:thread和threading,thread是低级模块,
	 threading是高级模块,对thread进行了封装。绝大多数情况下,
	 我们只需要使用threading这个高级模块。启动一个线程就是把一个
	 函数传入并创建Thread实例,然后调用start()开始执行
     def run():
	   print('主线程{},开始运行'.format(threading.current_thread().name))
	    n = 0
	    while n < 5:
	        n+=1
	        print('我是{}线程,---{}'.format(threading.current_thread().name,n))
	    print('线程{}, 结束了'.format(threading.current_thread().name))
	print('线程 %s is 运行...' % threading.current_thread().name)
	p = Thread(target=run,name='测试数据',daemon=True)
	p.start()
	p.join()
	print('线程{} 结束了'.format(threading.current_thread().name))
线程总结:
		1. threading.Thread(target,name,damemon,args,kwargs)
	       创建一个线程. target指定线程任务,name线程名,daemon为True守护线程
	       args,kwargs 为子线程中任务函数所需参数.
	
	    2. start()开启线程
	    3. join()等待线程结束.
	    4. 由于任何进程默认就会启动一个线程,我们把该线程称为主线程,主线程又可以启动新的线程,
	        Python的threading模块有个current_thread()函数,它永远返回当前线程的实例。主线程实例的名字叫MainThread,
	        子线程的名字在创建时指定,我们用LoopThread命名子线程。名字仅仅在打印时用来显示,完全没有其他意义,
	        如果不起名字Python就自动给线程命名为Thread-1,Thread-2……
	
	    5. 线程的属性.
	        p = threading.current_thread()
	        属性: p.name 线程名
	             p.ident 线程id
	             p.daemon 是否为守护线程
	        方法:
	              p.getName()
	              p.is_alive()
	              p.isDaemon()
	    6. threading中有用的几个方法
	       threading.currentThread(): 返回当前的线程变量。
	       threading.enumerate():返回一个包含正在运行的线程的list,正在运行指线程启动后,结束前,不包括启动前和终止后的线程。
	       threading.activeCount(): 返回正在运行的线程数量,与len(threading.enumerate())有相同的结果。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Python可以使用多进程或多线程实现抢票程序。以下是使用进程线程的示例: 使用进程实现抢票程序: ```python import multiprocessing import time def buy_ticket(lock, num): lock.acquire() # 加锁 if num > 0: print("第{}个进程,抢到一张票!".format(multiprocessing.current_process().name)) num -= 1 else: print("第{}个进程,票已售完!".format(multiprocessing.current_process().name)) lock.release() # 释放锁 if __name__ == '__main__': num = 10 # 假设有10张票 lock = multiprocessing.Lock() # 创建锁 processes = [] for i in range(5): # 创建5个进程 p = multiprocessing.Process(target=buy_ticket, args=(lock, num)) processes.append(p) p.start() for p in processes: p.join() # 等待所有进程结束 ``` 使用线程实现抢票程序: ```python import threading import time def buy_ticket(lock, num): lock.acquire() # 加锁 if num > 0: print("第{}个线程,抢到一张票!".format(threading.current_thread().name)) num -= 1 else: print("第{}个线程,票已售完!".format(threading.current_thread().name)) lock.release() # 释放锁 if __name__ == '__main__': num = 10 # 假设有10张票 lock = threading.Lock() # 创建锁 threads = [] for i in range(5): # 创建5个线程 t = threading.Thread(target=buy_ticket, args=(lock, num)) threads.append(t) t.start() for t in threads: t.join() # 等待所有线程结束 ``` 以上两个示例都使用了锁来保证多个进程线程修改共享变量(票数)时的互斥性。使用进程线程取决于具体的应用场景和需求。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值