python调用的是操作系统的原生线程,

表面是多线程,同一时间只有一个线程在运行,我们看到的多线程并发的现象,只是python利用的cpu的上下文切换,

cpu的计算速度很快,所以看起来是并发的效果。

所有如果你的代码是cpu密集型,用单线程比多线程效率可能更高,

如果是io密集型,用多线程的效率就很高了。

不够如果要用python确实的进行多线程,python里面也有折中的方法,需要几个线程就开启几个进程,每个进程里面的线程就可以起到多线程的真实效果。

最简单的python3多线程,代码如下:

import threading
import time

def run(t):
    print(t)
    time.sleep(1)

t1 = threading.Thread(target=run, args=("t1", ))
t2 = threading.Thread(target=run, args=("t2", ))

t1.start()
t2.start()



  

用类的方式开启多线程:



import threading
import time
"""
以类的方式启用多线程
"""

class MyThread(threading.Thread):
    def __init__(self, n, sleep_time):
        super(MyThread, self).__init__()
        self.n = n
        self.sleep_time = sleep_time

    def run(self):
        print("task:", self.n)
        time.sleep(self.sleep_time)
        print("task %s done" % self.n)

t1 = MyThread("t1", 2)
t2 = MyThread("t2", 4)

t1.start()
t2.start()
#等待t1线程执行完毕
t1.join()
print("----main thread----")



  

开启50个线程,并计算运行时间:



import threading
import time

start_time = time.time()
#创建空列表,存储每个线程对象
t_objs = []

def run(n):
    #打印当前运行的线程
    print("task, ", n, threading.current_thread())
    time.sleep(1)
    print("task %s done" % n)

#开启50个线程
for i in range(50):
    t = threading.Thread(target=run, args=(i, ))
    t.start()
    t_objs.append(t)

#等待所有线程执行完毕
for i in t_objs:
    t.join()

print("----all thread done----,", threading.current_thread())
print("cost:", time.time() - start_time)



  

守护线程:



import threading
import time
"""
守护线程
主人死了,仆人殉葬
"""

start_time = time.time()
t_objs = []

def run(n):
    #打印当前所在线程
    print("task, ", n, threading.current_thread())
    time.sleep(1)
    print("task %s done" % n)

for i in range(50):
    t = threading.Thread(target=run, args=(i, ))
    #守护线程,主线程执行完就退出程序,不等子线程
    t.setDaemon(True)
    t.start()
    t_objs.append(t)

#等待所有线程执行完毕再继续主线程
#for i in t_objs:
    #t.join()

print("----all thread done----,", threading.current_thread())
print("cost:", time.time() - start_time)



  

GIL全局锁:



import threading, time
"""
GIL 全局解释器锁
同一时间只有一个线程修改数据
同时修改数据的时候,避免出现差错
"""


def count():
    #加锁,每个线程进来都加锁,执行完当前线程之后,下一个线程再进来
    lock.acquire()
    global num
    num += 1
    print("curren_thread:", threading.current_thread())
    time.sleep(1)
    #解锁
    lock.release()

num = 0
#申请一把解释器锁
lock = threading.Lock()

t_objs = []
for i in range(50):
    t = threading.Thread(target=count)
    t.start()
    t_objs.append(t)

#子线程全部执行完毕,再继续主线程
for i in t_objs:
    i.join()


print("num:", num)



  

递归全局锁:



import threading, time
"""
递归锁
锁多的时候要用递归锁
避免钥匙搞乱,造成死循环
"""


def run1():
    global num1
    print("grab the first part data")
    lock.acquire()
    num1 += 1
    lock.release()
    return num1

def run2():
    global num2
    print("grab the second part data")
    lock.acquire()
    num2 += 1
    lock.release()
    return num2

def run3():
    lock.acquire()
    res1 = run1()
    print("----between run1 and run2----")
    res2 = run2()
    lock.release()
    print(res1, res2)

lock = threading.RLock()

num1, num2 = 0, 0

t_objs = []
for i in range(10):
    t = threading.Thread(target=run3)
    t.start()
    t_objs.append(t)

for i in t_objs:
    i.join()

while threading.active_count() != 1:
    print(threading.active_count())
else:
    print("all threads done")
    print(num1, num2)



  

BoundedSemaphore信号量:



import threading, time


def run(m):
    semaphore.acquire()
    print("task ", m)
    time.sleep(1)
    m += 1
    semaphore.release()

#设置信号量为5,最多允许5个线程同时运行
semaphore = threading.BoundedSemaphore(2)

for i in range(10):
    t = threading.Thread(target=run, args=(i, ))
    t.start()

while threading.active_count() != 1:
    pass
else:
    print("all threads done")



  

queue队列:



import queue, threading, time
"""
队列:
queue.Queue()        先进先出
queue.FiloQueue()    先进后出
queue.PrioriteQueue()   设置队列优先级
qsize() 打印队列大小
"""

q = queue.Queue(maxsize=10)


#生产者
def producer(name):
    count = 0
    while True:
        print("[%s]生产了骨头[%s]" % (name, count))
        q.put(count)
        count += 1
        time.sleep(2)

#消费者
def consumer(name):
    while True:
        print("[%s]吃了骨头[%s]..." % (name, q.get()))
        time.sleep(3)

p1 = threading.Thread(target=producer, args=("小白", ))

c1 = threading.Thread(target=consumer, args=("鹿晗", ))
c2 = threading.Thread(target=consumer, args=("皮几万", ))

p1.start()
c1.start()
c2.start()


  

event事件:


import threading, time
"""
event事件
功能类似于标志位
设置了事件线程可以通过,
清楚设置为线程不能通过
"""

def lighter():
    counter = 0
    event.set()
    while True:
        if counter > 5 and counter < 12:
            #清除标志位,阻塞,红灯
            event.clear()
            print("\033[41;1mred light is on...\033[0m")
        elif counter > 12:
            #设置标志位,放行,绿灯
            event.set()
            counter = 0
        else:
            print("\033[42;1mgreen light is on...\033[0m")
        time.sleep(1)
        counter += 1


def car(name):
    while True:
        #绿灯
        if event.is_set():
            print("[%s] run!" % name)
            time.sleep(1)
        else:
            print("[%s] sees red light, waiting...." % name)
            event.wait()
            print("[%s] sees green light, start going...." % name)


event = threading.Event()

lighter = threading.Thread(target=lighter)
lighter.start()

landrover = threading.Thread(target=car, args=("landrover", ))
tesla = threading.Thread(target=car, args=("tesla", ))
landrover.start()
tesla.start()