Python threading 多线程学习笔记

在计算机中,一个程序就是一个进程,一个进程里面可以有一个或多个线程,线程是真正使程序运行的东西。

关于进程和线程的关系,简单理解:进程与线程的一个简单解释


一、添加线程

1. threading模块

import threading

def main():
  print(threading.active_count()) # active threading numbers is 2
  print(threading.enumerate()) #[<_MainThread(MainThread, started 4321387392)>, <Thread(SockThread, started daemon 123145543471104)>]
  print(threading.current_thread()) #<_MainThread(MainThread, started 4321387392)>


if __name__ == '__main__':
    main()

2.添加线程

import threading

def thread_job():
    print("This is an added Thread, number is %s"%threading.current_thread())

def main():
    target=thread_job()
    added_thread = threading.Thread(target) #定义线程,接收参数target代表这个线程要完成的任务
    added_thread.start()
   

if __name__ == '__main__':
    main()


3.线程是各自工作互不干扰的,如下:

import threading
import time

def T1_job():
    print("T1 start\n")
    time.sleep(1) # 任务间隔1s
    print("T1 finish\n")

added_thread = threading.Thread(target=T1_job, name='T1') #注意此处target只是一个索引,所以不用函数的()
added_thread.start()
print("all done\n")

输出结果为

T1 start
all done




>>> T1 finish


你是不是认为这个程序应该输出的是

T1 start

T1 finish

all done

才对?


问题出现是因为主线程先于子线程结束。


怎么让子线程在主线程前门结束,主线程最后结束呢?

我们可以用join()

启动线程后,对它调用join()函数:

added_thread.start()
added_thread.join()
print("all done\n")

这一次all done会最后才输出。

所以用join来控制多线程的执行顺序是非常有用的。



4. Queue功能

将多线程的结果存储进Queue,看如下例子:

import threading
import time
import queue


def job(l,q): #对列表的每个元素进行平方计算,将结果保存在队列中
    for i in range(len(l)):
        l[i] = l[i]**2  #平方
    q.put(l) #多线程调用的函数不能用return返回值



def multithreading():
    q = queue.Queue()    #q中存放返回值,代替return的返回值
    threads = []  #定义一个多线程列表
    data = [[1,1],[2,3,4,5],[6],[7,8,9]]  #初始化一个多维数据列表,用来处理
    for i in range(4):   #定义四个线程
        t = threading.Thread(target=job,args=(data[i],q)) #Thread首字母要大写,被调用的job函数没有括号,只是一个索引,参数在后面
        t.start() #开始线程
        threads.append(t) #把每个线程append到线程列表中
    for thread in threads:  #分别join四个线程到主线程
        thread.join()

    results = []  #定义一个空的列表results
    for j in range(4): #将四个线程运行后保存在队列中的结果返回给空列表results
        results.append(q.get())  #q.get()按顺序从q中拿出一个值    
    print(results)

if __name__=='__main__':
    multithreading()

输出结果为:[[1, 1], [4, 9, 16, 25], [36], [49, 64, 81]]


5. 线程锁

对于两个线程同时操作一个共享的数据,如果不用锁,会造成数据混乱

如:(不用线程锁)

import threading

def job1():
    global A
    for i in range(10):
        A += 1
        print("job1:A=",A)


def job2():
    global A
    for i in range(10):
        A += 10
        print("job2:A=",A)
    

if __name__=='__main__':
    A = 0
    t1 = threading.Thread(target=job1)
    t2 = threading.Thread(target=job2)
    t1.start()
    t2.start()
    t1.join()
    t2.join()

输出结果为:

job1:A=job2:A=  111

job1:A=job2:A=  1222

job1:A=job2:A=  2333

job1:A=job2:A=  3444

job1:A=job2:A=  4555

job1:A=job2:A=  5666

job1:A=job2:A=  6777

job1:A=job2:A=  7888

job1:A=job2:A=  8999

job1:A=job2:A=  100110

使用线程锁:

在要操作数据前上锁,操作完数据后释放锁,这样就不会有同时修改数据的情况出现:

import threading

def job1():
    global A,lock
    lock.acquire()
    for i in range(10):
        A += 1
        print("job1:A=",A)
    lock.release()

def job2():
    global A,lock
    lock.acquire()
    for i in range(10):
        A += 10
        print("job2:A=",A)
    lock.release()

if __name__=='__main__':
    A = 0
    lock = threading.Lock()
    t1 = threading.Thread(target=job1)
    t2 = threading.Thread(target=job2)
    t1.start()
    t2.start()
    t1.join()
    t2.join()

输出结果为:

job1:A= 1
job1:A= 2
job1:A= 3
job1:A= 4
job1:A= 5
job1:A= 6
job1:A= 7
job1:A= 8
job1:A= 9
job1:A= 10
job2:A= 20
job2:A= 30
job2:A= 40
job2:A= 50
job2:A= 60
job2:A= 70
job2:A= 80
job2:A= 90
job2:A= 100
job2:A= 110






参考自:Threading 学会多线程

猜你喜欢

转载自blog.csdn.net/qq_20417499/article/details/80392423
今日推荐