线程: 线程是操做系统调度的最小单位,它包含在进程中。python
比喻:一条流水线工做的流程,一条流水线必须属于一个车间,一个车间的工做过程是一个进程,车间负责把资源整合到一块儿,是一个资源单位,而一个车间内至少有一个流水线,流水线的工做须要电源,电源就至关于cpuweb
建立一个进程,就是建立一个车间,涉及到申请空间,并且在该空间内建至少一条流水线,但建立线程,就只是在一个车间内造一条流水线,无需申请空间,因此建立开销小。安全
普通方式多线程
from threading import Thread def func(*args, **kwargs): print(args, kwargs) print('子线程启动啦') t = Thread(target=func, args=(1, 2, 3), kwargs={"name": 'jiangwei'}) t.start() print('开启了一个线进程')
类建立app
from threading import Thread class MyThread(Thread): def __init__(self, i): super(MyThread, self).__init__() self.i = i def run(self): time.sleep(1) print(self.i) t = MyThread(10) t.start()
不管是进程仍是线程,都遵循:守护xxx会等待主xxx运行完毕以后被销毁dom
注意:运行完毕并不是终止运行异步
def f1(): print('f1', 666) time.sleep(3) print('你都没死,我咋能先死,你先把其余人杀了再说') time.sleep(2.5) print('我发现我已经死了') def f2(): print('f2', 999) time.sleep(5) print('哈哈哈,他把我杀了') t1 = Thread(target=f1) t2 = Thread(target=f2) t1.daemon = True # 守护线程t1 t1.start() t2.start() print('主') # 主线程结束(等待其余非守护进程结束,也就是f2运行完毕)、守护进程随之结束(f1不会执行到print) """ f1 666 f2 999 主 你都没死,我咋能先死,你先把其余人杀了再说 哈哈哈,他把我杀了 """
解释器的代码是共享的,若是程序中有一个线程是修改全局变量n=100,而解释器里的垃圾回收线程执行回收n=100的操做,这就致使了数据混乱,不安全。socket
有了GIL的存在,同一时刻同一进程中只有一个线程被执行。那么,进程能够利用多核,但开销大,而线程开销小,却没法利用多核?函数
其实否则:
我开了一个工厂。假设个人原材料充足的状况下,个人工人越多越好,效率快。相似于cpu作计算.可是,若是个人原料不充足,要从西伯利亚运过来,那么个人工人越多越好吗?无济于事。相似于cpu作io读写操做。ui
两个或两个以上的进程或线程在执行过程当中,由于争夺资源而形成的互相等待的现象。若无外力做用,他们将没法推动下去,会进入死锁状态
能够屡次acquire,内部维护一个Lock和counter变量。counter记录acquire的次数,每加锁一次就+1。直到该线程的全部锁被释放,其余线程才能抢到
import time from threading import Lock, Thread, RLock # l1 = Lock() # l2 = Lock() # 递归锁 能够连续acquire屡次,每acquire一次,计数器+1 只要计数不为0,就不能被其余线程抢到 l1 = l2 = RLock() class MyThread(Thread): def run(self): self.f1() self.f2() def f1(self): l1.acquire() print('%s拿到了l1' % self.name) l2.acquire() print('%s拿到了l2' % self.name) l2.release() l1.release() def f2(self): l2.acquire() print('%s拿到了l1' % self.name) time.sleep(0.1) l1.acquire() print('%s拿到了l2' % self.name) l1.release() l2.release() if __name__ == '__main__': for i in range(10): t = MyThread() t.start()
也是一把锁,放多个钥匙。只不过再也不是家里的卫生间,而是公共厕所,每次能进入多人。
import time, random from threading import Thread, Semaphore, currentThread sm = Semaphore(5) def task(): with sm: print('%s ing ' % currentThread().getName()) time.sleep(random.randint(1, 3)) if __name__ == '__main__': for i in range(10): t = Thread(target=task) t.start()
主要是根据状态来控制线程
import time from threading import Thread, Event event = Event() def student(name): print('%s 正在听课' % name) event.wait() # event.wait(2) # 时间 print('%s 课间活动' % name) def teacher(name): print('%s 正在讲课' % name) time.sleep(7) event.set() # 改变状态为True,默认false event.clear()设为false if __name__ == '__main__': t = Thread(target=teacher, args=('jw',)) s1 = Thread(target=student, args=('alex',)) s2 = Thread(target=student, args=('wupeiqi',)) s3 = Thread(target=student, args=('egon',)) t.start() s1.start() s2.start() s3.start()
from threading import Timer def task(name): print('hello %s'%name) t = Timer(3,task,args=('egon',)) t.start()
import queue q = queue.Queue() # 先进先出--队列 q1 = queue.LifoQueue() # 后进先出--堆栈 q2 = queue.PriorityQueue() # 优先级队列 q2.put('a') q2.put('c') q2.put('a') print(q2.get()) print(q2.get()) print(q2.get())
import time, os, random from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor def task(name): print('name: %s pid:%s run' % (name, os.getpid())) time.sleep(random.randint(1, 3)) return '我是回调函数' def call_back(m): print(m.result()) if __name__ == '__main__': pool = ThreadPoolExecutor(5) t_list = [] for i in range(10): t = pool.submit(task, 'alex%s' % i) t.add_done_callback(call_back) t_list.append(t) pool.shutdown(wait=True) # close + join print('主') for t in t_list: print('----', t.result())