zoukankan      html  css  js  c++  java
  • 上海 day31--线程

    目  录

    一、线程相关理论

    1、什么是线程?

    线程是cpu调度的最小单位,能够独立运行。(进程是资源分配的最下单位,线程是CPU调度的最小单位

    进程:资源单位

    线程:执行单位

    如果将内存比作一个工厂的话,那进行就相当于一个车间,线程就是车间里面的流水线!

    PS: 每个进程都自带一个线程,线程才是真正的执行单位,进程只是在代码运行过程中提供所需要的资源!

    2、为什么需要线程?

    开进程
            1.申请内存空间  耗资源
            2."拷贝代码"    耗资源
    
    开线程
            一个进程内可以起多个线程,并且线程与线程之间数据是共享的
    ps:开启线程的开销要远远小于开启进程的开销

    3、线程与进程之间有什么区别?

    1)地址空间和其它资源(如打开文件):
     
      进程间相互独立,同一进程的各线程间共享。某进程内的线程在其它进程不可见。
     
    2)通信:
     
      进程间通信IPC,线程间可以直接读写进程数据段(如全局变量)来进行通信——需要进程同步和互斥手段的辅助,以保证数据的一致性。
     
    3)调度和切换:
     
      线程上下文切换比进程上下文切换要快得多。
     
    4)在多线程操作系统中
     
      进程不是一个可执行的实体。
     

    二、创建线程的两种方法

    使用模块:

      from threading import thread

    创建线程的注意事项:

    # 开线程不需要在__main__代码块内 但是习惯性的还是写在__main__代码块内

    方法一:

    from threading import Thread
    import time
    
    def run(name):
        print('%s is coming..'%name)
        time.sleep(3)
        print('%s is over'%name)
    
    if __name__ == '__main__':
        t = Thread(target=run,args=('egon',))
        t.start()  # 告诉操作系统开辟一个线程  线程的开销远远小于进程,小到t.start()代码执行完 线程就已经开启了
        print('主。。')
    '''
    执行结果:
        egon is coming..
        主。。
        egon is over
    为什么'egon is coming'子线程先执行,主线程后执行?
    
    '''

    方法二:

    from threading import Thread
    import time
    
    class MyThread(Thread):
        def __init__(self,name):
            super().__init__()
            self.name = name
    
        def run(self):
            print('%s is coming..' % self.name)
            time.sleep(3)
            print('%s is over'%self.name)
    
    # 不需要在 __main__ 下建立
    t = MyThread('jason')
    t.start()
    print('主。。')
    '''
    执行结果:
        jason is coming..
        主。。
        jason is over
    '''

    三、线程对象及其方法

    使用模块:

      from threading import  Thread, current_thread, active_thread

    current_thread  获得当前线程的名字

     active_thread   计算当前存活的进程数

    注意:

      线程之间是平等的关系,没有主次之分,我们只是认为的将其区分开!!!!

    from threading import Thread,current_thread,active_count
    import time
    
    def test(name):
        print('%s is running..'%name)
        print('子线程current_thread',current_thread().name)  # 获得子线程的名字
        time.sleep(2)
        print('%s is ending'%name)
    
    t = Thread(target=test,args=('jason',))
    # t = Thread(target=test,args=('jason,'))
    t.start()
    print('主。。')
    print('主线程current_thread',current_thread().name)  # 获得主线程的名字

    验证线程的os.getpid()  以及判断线程的存活数

    代码如下:

    from threading import Thread,current_thread,active_count
    import time
    import os 
    
    def test(name,i):
        print('%s is running..'%name)
    
        print('', os.getpid())  # 获取子线程的进程号
        time.sleep(i)
        print('%s is ending'%name)
    
    t1 = Thread(target=test,args=('jason',1))
    t2 = Thread(target=test,args=('egon',3))
    # t = Thread(target=test,args=('jason,'))
    t1.start()
    t2.start()
    # t2.join()  # 主进程等待子进程运行完毕。。。
    # print('主。。',active_count())  # 1个线程
    t1.join()  # 主进程等待子进程运行完毕。。。
    print('主。。',active_count())  # 2个线程
    print('',os.getpid())  # 获取主线程的进程号 —— 得知主线程和子线程的进程号相同,验证同属一个进程
    '''
    执行结果如下:
    jason is running..
    子 9980
    egon is running..
    子 9980
    jason is ending
    主。。 2
    主 9980
    egon is ending
    '''

    四、线程间共享数据

    线程间共享数据即多个线程操作同一份数据!

    代码验证:

    from threading import  Thread
    
    money = 1000
    def run():
        global money
        money = 999
    
    t = Thread(target=run)
    t.start()
    print(money)  # 999  说明主线程和子线程两者共享数据,即操作同一份数据

    五、守护线程 ******

    from threading import Thread,current_thread
    import time
    
    def run(i):
        print(current_thread().name)
        time.sleep(i)
        print('GGGGGG')
    
    t1 = Thread(target=run,args=(1,))
    t2= Thread(target=run,args=(3,))
    t1.daemon = True   # 设置守护线程!!!!!!
    t1.start()
    t2.start()
    print('主。。')
    '''
    执行结果:
    Thread-1
    Thread-2
    主。。
    GGGGGG
    GGGGGG
    '''
    '''
    提出问题:为什么主线程结束了,守护线程还可以执行?
    
    主线程的结束也就意味着进程的结束
    主线程必须等待其他非守护线程的结束才能结束
    (意味子线程在运行的时候需要使用进程中的资源,而主线程一旦结束了资源也就销毁了)
    '''

    六、线程互斥锁

    代码示例:

    from threading import Thread,Lock
    import time
    
    
    n = 100
    
    def task(mutex):
        global  n
        mutex.acquire()
        tmp = n
        time.sleep(0.1)
        n = tmp - 1
        mutex.release()
    
    t_list = []
    mutex = Lock()
    for i in range(100):
        t = Thread(target=task,args=(mutex,))
        t.start()
        t_list.append(t)
    for t in t_list:
        t.join()
    print(n)

     代码释义:

    我们先开了100个线程,为了达到并发的效果,我们将开启的100个线程添加到列表中,然后在循环列表里的线程为线程加 join方法来确保每个线程都可以执行完毕!!

    小例子:

    from threading import Thread
    from multiprocessing import Process
    import time
    def foo():
        print(123)
        time.sleep(1)
        print("end123")
    
    def bar():
        print(456)
        time.sleep(3)
        print("end456")
    
    if __name__ == '__main__':
        t1=Thread(target=foo)
        t2=Thread(target=bar)
        t1.daemon=True
        t1.start()
        t2.start()
        print("main-------")

    程序执行结果是什么?

  • 相关阅读:
    winform 调用http 通过代理出现的一系列问题
    【转】 CSS3阴影 box-shadow的使用和技巧总结
    【转】 C#程序以管理员权限运行
    【转】WMI使用的WIN32_类库名
    【转】C#取硬盘、CPU、主板、网卡的序号 ManagementObjectSearcher
    【转】纯CSS设置Checkbox复选框控件的样式
    【转】vs2012 打包安装更改 setup.exe的图标
    【转】VS2012程序打包部署详解
    142. Linked List Cycle II
    141. Linked List Cycle
  • 原文地址:https://www.cnblogs.com/qinsungui921112/p/11341129.html
Copyright © 2011-2022 走看看