进程就是程序执行的载体,我们打开的每个软件、游戏,执行的每一个Python脚本都是启动一个进程。
线程是进程中执行运算的最小单位,是进程中的一个实体,是被系统独立调度和分派的基本单位。例如车间的生产是一个进程,那每个流水线就是它的一个线程。
线程自己不拥有系统资源,只拥有一点在运行中必不可少的资源,但它可与同属一个进程的其它线程共享进程所拥有的全部资源。一个线程可以创建和撤消另一个线程,同一进程中的多个线程之间可以并发执行。
进程提供线程执行程序的前置要求,线程在重组的资源配备下,去执行程序。Python3线程中常用的两个模块是“_thread”和“threading”(推荐使用)。
thread模块已被废弃。用户可以使用threading模块代替。所以,在Python3中不能再使用“thread”模块。为了兼容性,Python3将thread重命名为“_thread”。
class threading.Thread(group=None,target=None,name=None,args=(),kwargs={})
join | 阻塞直到线程执行结束。这会阻塞调用这个方法的线程,直到被调用join的线程终结-不管是正常终结还是抛出未处理异常-或者直到发生超时,超时选项是可选的。 一定要在join()后调用is_alive()才能判断是否发生超时-如果线程仍然存活,则join()超时。一个线程可以被join()很多次 |
join(timeout=none) |
getName | 获取线程的名字 | getName() |
setName | 设置线程的名字 | setName(name) |
is_alive | 判断线程是否存活 | is_alive() |
setDaemon |
守护进程 | setDaemon(True) |
将一个函数对象从类的构造器传递进去,这个对象就是回调函数,用来处理任务
from threading import Thread
def task():
print( "I am Sub_Thread")
if __name__== "__main__":
t = Thread(target=task)
t.start()
print("I am Main_Thread")
结果打印如下:
I am Sub_Thread
I am Main_Thread
编写一个自定义类继承Thread,然后重写run()方法,在run()方法中编写任务处理代码,然后创建这个Thread的子类。
from threading import Thread
class MyThread(Thread):
def run(self):
print("I am Sub_Thread")
if __name__== "__main__":
t = MyThread()
t.start()
print("I am Main_Thread")
结果打印如下:
I am Sub_Thread
I am Main_Thread
多线程类似于车间生产时,有多条流水线在运作,可以提高生产的效率。创建Thread对象,然后让它们运行,每个Thread对象代表一个线程,在每个线程中我们可以让程序处理不同的任务,这就是多线程编程。
这里创建了7个线程执行任务,同时调用join方法等待线程执行结束,比单一主线程执行更加快速
import threading
def func(n):
while n>0:
print( "CurrentThread Num:{0}: CurrentThread Name:{1} ".format(threading.activeCount(),threading.currentThread().name))
n-=1
threads = []
for x in range(5):
t = threading.Thread(target=func ,args=(2,))
threads.append(t)
t.start()
for t in threads:
t.join()
print("MainThread:",threading.currentThread().name)
结果打印如下:
CurrentThread Num:2: CurrentThread Name:Thread-2
CurrentThread Num:3: CurrentThread Name:Thread-2
CurrentThread Num:2: CurrentThread Name:Thread-3
CurrentThread Num:2: CurrentThread Name:Thread-3
CurrentThread Num:2: CurrentThread Name:Thread-4
CurrentThread Num:3: CurrentThread Name:Thread-4
CurrentThread Num:2: CurrentThread Name:Thread-5
CurrentThread Num:3: CurrentThread Name:Thread-6
CurrentThread Num:3: CurrentThread Name:Thread-6
CurrentThread Num:2: CurrentThread Name:Thread-5
MainThread: MainThread
如果多个线程共同对某个数据修改,则可能出现不可预料的结果,为了保证数据的正确性,需要对多个线程进行同步。使用Thread对象的Lock和Rlock可以实现简单的线程同步。
def job1():
global A , lock
lock.acquire()
for i in range(10):
A+=1
print("Job1",A)
lock.release()
def job2():
global A ,lock
lock.acquire()
for i in range(10):
A+=10
print("Job2",A)
lock.release()
if __name__ == "__main__":
lock= threading.Lock()
A=0
t1 = threading.Thread(target=job1)
t2 = threading.Thread(target=job2)
t1.start()
t2.start()
t1.join()
t2.join()
结果打印如下:
Job1 1
Job1 2
Job1 3
Job1 4
Job1 5
Job1 6
Job1 7
Job1 8
Job1 9
Job1 10
Job2 20
Job2 30
Job2 40
Job2 50
Job2 60
Job2 70
Job2 80
Job2 90
Job2 100
Job2 110
执行后,t1先获得锁,执行完成后再释放锁,t2再获得锁,继续执行后再释放锁,这样避免同时处理,导致数据出错。
lock = threading.RLock()
ret = lock.acquire()
print(ret)
ret = lock.acquire(timeout=3)
print(ret)
ret = lock.acquire(True)
print(ret)
ret = lock.acquire(False)
print(ret)
结果打印如下:
True
True
True
True