python 多线程 多进程
多线程
多线程类似于同时执行多个不同程序,多线程运行有如下优点:
- 使用线程可以把占据长时间的程序中的任务放到后台去处理。
- 用户界面可以更加吸引人,这样比如用户点击了一个按钮去触发某些事件 的处理,可以弹出一个进度条来显示处理的进度,程序的运行速度可能加快
- 在一些等待的任务实现上如用户输入、文件读写和网络收发数据等,我们 可以释放一些珍贵的资源如内存占用等等。
- 线程可以被抢占(中断)。
- 在其他线程正在运行时,线程可以暂时搁置
Python中使用线程有两种方式:函数或者用类来包装线程对象。
函数式:调用thread模块中的start_new_thread()函数来产生新线程。
使用Threading模块创建线程:直接从threading.Thread继承,然后重写__init__
方法和run方法:
线程模块
Python通过两个标准库thread和threading提供对线程的支持。thread提供了低级别的、原始的线程以及一个简单的锁。
thread 模块提供的其他方法:
- threading.currentThread(): 返回当前的线程变量。
- threading.enumerate(): 返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后的线程。
- threading.activeCount():返回正在运行的线程数量,与len(threading.enumerate())有相同的结果。
除了使用方法外,线程模块同样提供了Thread类来处理线程,Thread类提供了以下方法:- run(): 用以表示线程活动的方法。
- start():启动线程活动。
- join([time]): 等待至线程中止。这阻塞调用线程直至线程的join() 方法被调用中止-正常退出或者抛出未处理的异常-或者是可选的超时发生。
- isAlive(): 返回线程是否活动的。
- getName(): 返回线程名。
- setName(): 设置线程名。
使用Threading模块创建线程:
import threading
import time
Flag = 0
class myThread (threading.Thread):
#继承父类threading.Thread
def __init__(self, threadID, name, counter):
threading.Thread.__init__(self)
self.threadID = threadID
self.name = name
self.counter = counter
def run(self):
#把要执行的代码写到run函数里面线程在创建后会直接运行run函数
print ("Starting " + self.name)
print_time(self.name, self.counter, 5)
print ("Exiting " + self.name)
def print_time(threadName, delay, counter):
while counter:
if Flag:
thread.exit()
time.sleep(delay)
print ("%s: %s" % (threadName, time.ctime(time.time())))
counter -= 1
# 创建新线程
thread1 = myThread(1, "Thread-1", 1)
thread2 = myThread(2, "Thread-2", 2)
# 开启线程
thread1.start()
thread2.start()
print ("Exiting Main Thread")
线程同步——锁
import threading
import time
class Num:
def __init__(self):
self.num=0
self.lock=threading.Lock()
def add(self):
self.lock.acquire()
#加锁,锁住相应的资源
self.num+=1
num=self.num
self.lock.release()
#解锁,释放该资源
return num
s=Num()
class thread(threading.Thread):
def __init__(self,item):
threading.Thread.__init__(self)
self.item=item
def run(self):
time.sleep(2)
value=s.add()
print (self.item,value)#序号,值
for item in range(4):
t=thread(item)
t.start()#启动线程活动
t.join() # 等待至线程中止
多进程
线程在执行过程中与进程还是有区别的。每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。
获取当前进程并创建子进程
from multiprocessing import Process
import os
# 子进程要执行的代码
def run_proc(name):
print('Run child process %s (%s)...' % (name, os.getpid()))
if __name__=='__main__':
print('Parent process %s.' % os.getpid())
p = Process(target=run_proc, args=('test',))
print('Child process will start.')
p.start()
p.join()
print('Child process end.')
多进程调用
from multiprocessing import Pool
import os,time,random
def long_time_task(name):
print('运行任务 %s (%s)...' % (name,os.getpid()))
start = time.time()
#开始时间戳
time.sleep(random.random()*10)
#time.sleep()函数推迟调用线程的运行,可通过参数secs指秒数,表示进程挂起的时间。
end = time.time()
#结束时间
print('任务 %s 运行了 %0.2f 毫秒' % (name,(end-start)))
#结束时间减去开始时间
if __name__=='__main__':
print('父进程是 %s' % os.getpid())
p=Pool(4)
for i in range(5):
p.apply_async(long_time_task,args=(i,));
#异步非阻塞生成子进程 ///
print('Waiting for all subprocesses done .....')
p.close()
p.join()
print('所有线程已运行完毕')
使用进程池
import multiprocessing
import time
def func(msg):
#要放在子进程中执行的代码
for i in range(2):#运行次数
print (msg)
time.sleep(2)#间隔时间
return "done"+msg
if __name__=='__main__':
pool=multiprocessing.Pool(processes=3)#每次运行的进程数
#创建一个新进程
res=[]
for i in range(5):
msg="hello %d"%(i)
res.append(pool.apply_async(func,(msg,)))
pool.close()
pool.join()
for r in res:
print (r.get())
print ("运行结束")