zoukankan      html  css  js  c++  java
  • 二十九、线程与多线程

    一、线程定义及作用

    线程:进程线程其实都是虚拟单位,都是用来帮助我们形象的描述某种事物
    进程:资源单位(进程开辟一块内存空间,里面可以有多个线程)
    线程:执行单位(进程的任务都是线程去执行)
    将内存比如成工厂
    那么进程就相当于是工厂里面的车间
    而你的线程就相当于是车间里面的流水线
    ps:每个进程都自带一个线程,线程才是真正的执行单位,进程只是在线程运行过程中
    提供代码运行所需要的资源

    线程的作用:
    开进程:
    1.申请内存空间 耗资源
    2."拷贝代码" 耗资源

    开线程
    一个进程内可以起多个线程,并且线程与线程之间数据是共享
    ps:开启线程的开销要远远小于开启进程的资源占有
      比如:一个进程在运行过程中遇到阻塞,要么只能等待,
    要么就需要多启动一个进程去执行提高运算速度,

    这时候 线程 就可以在不多开启进程的情况下,异步去执行其他代码,提高效率
    (进程在同一时间只能干一件事,要想同时干几件事就显得无能为力)

      注意:进程是资源分配的最小单位,线程是cpu调度的最小单位
    每一个进程中至少有一个线程
    
    

    二、创建线程的两种方式

    from threading import Thread
    import time
    
    
    def task(name):
        print('%s is running' % name)
        time.sleep(3)
        print('%s is over' % name)
    
    
    # 开线程不需要在__main__代码块内 但是习惯性的还是写在__main__代码块内
    t = Thread(target=task, args=('egon',))
    t.start()  # 告诉操作系统开辟一个线程  线程的开销远远小于进程
    # 小的代码执行完 线程就已经开启了
    print('')
    
    """第二种方法:
    from threading import Thread
    import time
    
    
    class MyThread(Thread):
        def __init__(self, name):
            super().__init__()
            self.name = name
    
        def run(self):
            print('%s is running' % self.name)
            time.sleep(3)
            print('%s is over' % self.name)
    
    
    t = MyThread('egon')
    t.start()
    print('主')
    就是继承Thread得来"""

    三、线程对象及其他方法

    子线程与子线程,主线程都是异步(同时)运行,并且都是同一个进程
    from threading import Thread, current_thread, active_count
    import time, os
    
    
    def task(name, i):
        print("%s is runing" % name)
        print("子线程名字:", current_thread().name)  # 子线程名字
        print("子线程进程:", os.getpid())
        time.sleep(1)
        print("%s is over" % name)
    
    # active_count() 当前活跃线程数:
    # current_thread().name 线程名字(是主线程或子线程名字)
    # os.getpid()查询进程数
    t1 = Thread(target=task, args=("engon", 1,)) t2 = Thread(target=task, args=("tank", 2,)) t1.start() t2.start() # t1.join() # t2.join() #等待子线程结束 print("当前正在活跃的线程数:", active_count()) print("主线程名字:", current_thread().name) # print("主线程进程:", os.getpid()) # 只要不是子线程,都是主线程

    四、守护线程

    主线程的结束也就意味着进程的结束
    主线程必须等待其他非守护线程的结束才能结束
    (意味子线程在运行的时候需要使用进程中的资源,而主线程一旦结束了资源也就销毁了)
    from threading import Thread, current_thread
    import time
    
    
    def task(i):
        print(current_thread().name)
        time.sleep(i)
        print('GG')
    
    
    # for i in range(3):
    #     t = Thread(target=task,args=(i,))
    #     t.daemon = True
    #     t.start()
    t = Thread(target=task, args=(1,))
    t.daemon = True  # 开启子线程守护线程
    t.start()
    print('')

    五、线程之间的通讯

     同一个进程里,所有线程的数据都是共享的,因为都在同一个内存空间(进程开辟的空间)
    from threading import Thread
    
    
    money = 666
    
    def task():
        global money
        money = 777
    
    t = Thread(target=task)
    t.start()
    t.join()
    print(money) #777

    六、线程锁(互斥锁)

    线程锁:和进程锁使用方法一样,开启多线程中会存在数据不安全(多个线程抢同一个数据)
    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) #0
    # 100个线程异步去执行task(),拿到锁以后一个一个运行,保证数据安全
    from threading import Thread
    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-------")
    小练习
  • 相关阅读:
    怎样在黑窗口中查找各种端口
    [Selenium] 数字显示的月份转换为英文显示
    [Selenium] 根据预期的日期格式,获取昨天的日期
    [Selenium] 使用Javascript选中Input框里的内容,然后清空
    Java中for循环遍历List的两种方法
    [Selenium]点击Calendar控件后,Calendar dialog很快消失
    springboot @Slf4j 配置
    springboot线程中获取spring beans
    org.junit.Test 注解失效的问题The import org.junit cannot be resolved
    二叉树java遍历实现
  • 原文地址:https://www.cnblogs.com/wukai66/p/11340709.html
Copyright © 2011-2022 走看看