1,一个cpu一次只能执行一个任务, 多个cpu同时可以执行多个任务
2,一个cpu一次只能执行一个进程, 其他进程处于非运行状态
3,进程里包含的执行单元叫线程,一个进程可以包含多个线程
4,一个进程的内存空间是共享的,每个进程里的线程都可以使用这个共享空间
5,一个线程在使用这个共享空间的时候, 其它的线程必须等待(阻塞状态)
6,互斥锁作用就是防止多个线程同时使用这块内存空间, 先使用的线程会将空间上锁, 其它的线程处于等待状态, 等锁开了才能进
7,进程: 表示程序的一次执行
8,线程:CPU运算的基本调度单位
9,GIL(全局锁):Python里的执行通行证, 而且只有一个, 拿到通行证的线程就可以进入CPU执行任务, 没有GIL的线程就不能执行任务
10, Python的多线程适用于大量密集的I/O处理
11,Python的多进程适用于大量的密集并行计算

 

添加线程
threading.Thread(target, args)
使用threading.Thread()新建一个线程, target是需要执行的函数, args是需要传入该函数的参数, args接受一个tuple, 即使只有一个参数 也需要写成(x,)形式
import threading

def thread_job():
    print('1111')

def main():
    thread = threading.Thread(target=thread_job,) # 添加一个线程
    thread.start()  # 开始该线程


if __name__ == '__main__':
    main()

 

线程阻塞:join
join()的作用是调用该线程时, 等待该线程完成之后在继续往下执行
join通常用于主线程与子线程之间, 主线程等待子线程运行完毕后在继续执行, 避免子程序和主程序同时执行, 子程序还没有运行完的时候就已经运行结束
import threading
import time

def T1_job():
    print('T1 start\n')
    for i in range(10):
        time.sleep(10)
    print('T1 finish\n')


def T2_job():
    print('T2 start\n')
    print('T2 finish\n')


def main():
    thread1 = threading.Thread(target=T1_job, name='T1')  
    thread2 = threading.Thread(target=T2_job, name='T2')  
    thread1.start()
    thread1.join()  # 等待执行thread1完成后才能进行下一步-主程序
    thread2.start()
    thread2.join()
    print('all done')


if __name__ == '__main__':
    main()

 

Queue(队列对象)
Queue是Python中的标准库, 可以直接import Queue引用, 队列是线程间最常用的交换数据的形式
Python下多线程的思考
对于资源, 加锁是个重要的环节, 因为Python原生的list ,dict等, 都是 not thread safe的, 而Queue,是线程安全的, 因此在满足使用条件下, 建议使用队列
1, 初始化: class.Queue.Queue(maxsize) FIFO先进先出
2, 包中国的常用方法:
Queue.qsize()返回队列的大小
Queue.empty()如果队列为空, 返回True,反之False
Queue.full()如果队列满了, 返回True,反之False
Queue.full与maxsize大小对应
Queue.get([block[, timeout]])获取队列, timeout等待时间
3, 创建一个"队列"对象
import Queue
myqueue = Queue.Queue(maxsize=10)
4,将一个值放入队列中
myqueue.put(10)
5,将一个值从队列中取出
myqueue.get()


import threading
from queue import Queue

"""
# Queue是python标准库中的线程安全的队列(FIFO)实现, 提供了一个适用于多线程编程的先进先出的数据结构,即队列.
# Queue是一种先进先出的数据结构, 一般来说读数据都从Queue头读, 写数据都从Queue尾写入
# """

def job(l,q):
for i in range(len(l)):
l[i] = l[i] ** 2
q.put(l) # 线程中, return获取的值无法提取, 需要放入q中

def multithreading():
q = Queue() # 队列
threads = [] # 全部线程
data = [[1, 2, 3], [3, 4, 5], [4, 4, 4], [5, 5, 5]]
for i in range(4):
t = threading.Thread(target=job, args=(data[i], q)) # 4个线程来执行job函数
t.start()
threads.append(t) # 当前线程加入全部线程中

# 对主线程的每一个线程都执行join()
for thread in threads:
thread.join()

results = [] # 保存结果
for _ in range(4):
results.append(q.get()) # 从q中取值, 每次只能按顺序拿出一个值
print(results)

if __name__ == '__main__':
multithreading()


 

"""
线程锁:Lock
lock在不同线程使用同一共享内存时, 能够确保线程之间互不影响
使用lock的方法是: 在每个线程执行运算修改共享内存之前执行lock.acquire()将共享内存上锁, 确保当前线程执行时, 内存不会被其他线程访问; 执行运算完毕后使用lock.release() 将锁关闭, 保证其他的线程可以使用该共享内存. lock.acquire()和lock.release()必须成对出现
下面代码 将lock.acquire(), lock.release()注释掉后, 输出结果是混乱的, 加锁后, 输出结果按顺序执行

# """

def job1():
    global A, lock
    lock.acquire()  # 打开锁
    for i in range(10):
        A += 1
        time.sleep(2)
        print('job1', A)
    lock.release()  # 关闭锁

def job2():
    global A, lock
    lock.acquire()  # 打开锁
    for i in range(10):
        A += 10
        time.sleep(2)
        print('job2', A)
    lock.release()  # 关闭锁

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

 

import threading
from multiprocessing.dummy import Pool as ThreadPool

"""
线程池有几种方法可以实现, 这里我们使用multiprocessing.dummy库
"""
def job(i):
    print(i, '\n', threading.current_thread())

if __name__ == '__main__':
    pool = ThreadPool(4)  # 创建一个包含4个线程的线程池
    pool.map(job, range(12))
    pool.close()  # 关闭线程池的写入
    pool.join()  # 阻塞, 保证子线程运行完毕后在继续主进程

 

posted on 2019-08-07 09:40  wy0925  阅读(164)  评论(0编辑  收藏  举报