线程的理论

线程的理论知识

1.什么是线程

​ 一条流水线的工作流程

之前描述的进程 : 在内存中开启一个进程空间,然后将主进程的所有资源数据复制一份,然后调用 CPU 执行这些代码

之前描述的进程不够具体,具体的应该是这样: 在内存中开启一个进程空间,然后将主进程的所有资源数据复制一份,然后调用线程去执行这些代码

进程是资源单位,线程是执行单位(线程是 CPU 最小的执行单位,进程是由线程执行的)

以后你描述一个开启一个进程 :在内存中开启一个进程空间,然后将主进程的所有资源数据复制一份,然后调用线程去执行这些代码

2.线程 VS 进程

  1. 开启进程的开销非常大,比开启线程的开销大很多
  2. 开启线程的速度非常快,要大几十甚至几百倍
  3. 线程线程之间可以共享数据,进程进程之间必须借助队列等方法实现通信

3.线程的应用

并发 : 一个 CPU 看起来像是执行多个任务

单个进程开启三个进程

开启三个进程并发的执行任务

文本编辑器

  1. 输入文字
  2. 在屏幕上显示
  3. 保存在磁盘中

开启多线程就非常好了 就非常好了 因为你要是打开三个窗口 ,不方便

数据共享,开销小,速度快

4.开启线程的两种方式

第一版

from threading import Thread
import time
def task(name):
    print(f"{name} is running")
    time.sleep(1)
    print(f"{name} is gone")
if __name__ == '__main__':
    t1 = Thread(target = task,args=("海狗",))
    t1.start()
    print("====主线程")
#  执行的速度非常快

第二版

没传参数的情况

from threading import Thread
import time
class MyThread(Thread):
    def run(self):
        print(f"{self.name} is running")
        time.sleep(1)
        print(f"{self.name} is gone")
if __name__ == '__main__':
    t1 = MyThread ()
    t1.start()
    print("====主线程")
    
'''
Thread-1 is running
====主线程
Thread-1 is gone    类似于进程中不传 self.name 输出的结果是 process - 1
'''

传参数的情况

from threading import Thread
import time
class MyThread(Thread):
    def __init__(self,name,l1,s1):
        super().__init__()
        self.name = name
        self.l1 = l1
        self.s1 = s1

    def run(self):
        print(f"{self.name} is running")
        time.sleep(1)
        print(f"{self.name} is gone")
if __name__ == '__main__':
    t1 = MyThread ('魏无羡',[1,2,3],"180")
    t1.start()
    print("====主线程")

'''
魏无羡 is running
====主线程
魏无羡 is gone
'''

5.线程进程 pid

主线程和子线程没有地位之分,这就引出了一个问题?

一个进程究竟谁在干活?

一个主线程在干活,当干完活了,你得等待其他线程干完活之后,才能结束本线程.

一个进程下的主线程和主进程共用一个 pid 可以这样理解,他们在一个空间里嘛

from threading import Thread
import os
def task():
    print(os.getpid())
if __name__ == '__main__':
    t1 = Thread(target = task)
    t2 = Thread(target = task)
    t1.start()
    t2.start()
    print(f"主线程{os.getpid()}")
'''
59998
59998
主线程59998   不变不变

6.同一个进程,线程是共享数据的

  1. 进程:子进程和主进程是隔离的
  2. 线程:共享
  3. 同一进程的资源数据对于这个进程的多个线程来说是共享的
from threading import Thread
import os
x = 3
def task():
    global x
    x = 100
if __name__ == '__main__':
    t1 = Thread(target = task)
    t2 = Thread(target = task)
    t1.start()
    t2.start()
    print(f"主线程:{x}")
#  主线程:100     你看改变了  不是

7.线程的其他方法

几个方法全部都在里了哦

from threading import Thread
from threading import currentThread
from threading import enumerate
from threading import activeCount
import os
import time
x = 3
def task():
    time.sleep(1)
    print(666)
if __name__ == '__main__':
    t1 = Thread(target = task,name = '线程 1')
    t2 = Thread(target = task,name = '线程 2')
    #  设置线程名
    t1.start()
    t2.start()

    time.sleep(1)
    print(t1.isAlive())    #  判断线程是否活着  返回 True or False
    # print(t1.getName())  #  获取线程名
    # t1.setName('子线程-1')   #  修改线程名
    # print(t1.name)         #  获取线程名   重要****************************************

    # print(currentThread()) # 获取当前线程的对象,并且是主线程哦
    # print(enumerate())   # 返回一个列表,包含所有的线程对象
    # print(activeCount()) #  返回活着的线程数   重要***************************************
    # print(f"===主线程{os.getpid()}")

8.join 与守护线程

并发的情况

from threading import Thread
import time
def task(name):
    print(f"{name} is running")
    time.sleep(1)
    print(f"{name} is gone")
if __name__ == '__main__':
    start_time = time.time()
    t1 = Thread(target = task,args = ('海狗',))
    t2 = Thread(target = task,args = ('海狗1',))
    t3 = Thread(target = task,args = ('海狗2',))
    t1.start()
    t2.start()
    t3.start()

    t1.join()
    t2.join()
    t3.join()
    print(f"主线程{time.time() - start_time}")

'''
海狗 is running
海狗1 is running
海狗2 is running
海狗 is gone
海狗1 is gone
海狗2 is gone
主线程1.0073320865631104

串行的情况 : 一个一个的执行

from threading import Thread
import time
def task(name):
    print(f"{name} is running")
    time.sleep(1)
    print(f"{name} is gone")
if __name__ == '__main__':
    start_time = time.time()
    t1 = Thread(target = task,args = ('海狗',))
    t2 = Thread(target = task,args = ('海狗1',))
    t3 = Thread(target = task,args = ('海狗2',))
    t1.start()
    t1.join()
    t2.start()
    t2.join()
    t3.start()
    t3.join()
    print(f"主线程{time.time() - start_time}")

'''
海狗 is running
海狗 is gone
海狗1 is running
海狗1 is gone
海狗2 is running
海狗2 is gone
主线程3.0137791633605957
'''

回忆一下守护进程

from multiprocessing import Process
import time
def foo():
    print(123)
    time.sleep(1)
    print('end123') #  随着主进程的结束这个就不执行了
def bar():
    print(456)
    time.sleep(1)
    print('end456')
if __name__ == '__main__':
    p1 = Process(target = foo)
    p2 = Process(target = bar)

    p1.daemon = True
    p1.start()
    p2.start()
    print('===主')
'''
===主
123
456
end456
'''

我们看一下守护线程,结果很秀

简单版本的

from  threading import Thread
import time
def sayhi(name):
    print('你滚')
    time.sleep(2)
    print("%s say hello"%name)
if __name__ == '__main__':
    t = Thread(target = sayhi,args = ('大黄',))
    t.setDaemon(True)   #  必须在t.start()之前
    # t.daemon = True   这个也是
    t.start()
    print("主线程")
'''
你滚
主线程
'''

下面两版作对比

from threading import Thread
import time
def foo():
    print(123)
    time.sleep(1)
    print('end123')
def bar():
    print(456)
    time.sleep(1)
    print('end456')

t1 = Thread(target = foo)
t2 = Thread(target = bar)

t1.daemon = True
t1.start()
t2.start()
print("main------")
'''
123
456
main------
end123
end456

'''


注意end123 输出来了

将上面时间改一下,结果就变了

from threading import Thread
import time
def foo():
    print(123)
    time.sleep(3)
    print('end123')
def bar():
    print(456)
    time.sleep(1)
    print('end456')

t1 = Thread(target = foo)
t2 = Thread(target = bar)

t1.daemon = True
t1.start()
t2.start()
print("main------")
'''
123
456
main------
end456
'''

总结 : 守护线程等待非守护线程以及主线程结束后结束

PS : 就是主线程等其他进程,守护进程等待主线程

需要重点理解的,还没加锁的情况

from threading import Thread
import time
import random
x = 100
def task():
    time.sleep(random.randint(1,2))
    global x
    temp = x
    time.sleep(random.randint(1, 2))
    temp = temp - 1
    x = temp
if __name__ == '__main__':
    l1 = []
    for i in range(100):
        t = Thread(target = task)
        l1.append(t)
        t.start()
        #t.join()  这里的结果是串行,自己测试的
    for i in l1:
        i.join()   
        '''
        放在这里的效果相当于并发   就像是之前的那个代码,1  2  3   
        join放在下面  一样  但 要是紧跟着,那就是串行,这里还是并发
        运行速度非常快,一窝蜂全部拿到  x = 100  不是其他人不执行,而是
        结果都是一样的 99
        '''
        print(f"主线程:{x}")

多个任务公抢一个资源时,要让其串行,所以选择加锁

from threading import Thread
from threading import Lock
import time
import random
x = 100
def task(lock):
    lock.acquire()
    global x
    temp = x
    time.sleep(0.01)
    temp = temp - 1  #  这样写的原因是这一步执行太快,所以写开
    x = temp
    lock.release()

if __name__ == '__main__':
    mutex = Lock()
    l1 = []
    for i in range(100):
        t = Thread(target = task,args = (mutex,))
        l1.append(t)
        t.start()

    time.sleep(3)
    print(f'主进程{x}')
'''
主进程0  这是最终的结果
'''
posted @ 2019-08-22 17:34  挂机兄  阅读(125)  评论(0编辑  收藏  举报