zoukankan      html  css  js  c++  java
  • Python学习-day9 线程

    这节内容主要是关于线程的学习

    首先要了解的什么是进程,什么是线程

    进程与线程

    什么是进程(process)?

    程序并不能单独运行,只有将程序装载到内存中,系统为它分配资源才能运行,而这种执行的程序就称之为进程。程序和进程的区别就在于:程序是指令的集合,它是进程运行的静态描述文本;进程是程序的一次执行活动,属于动态概念。

    在多道编程中,我们允许多个程序同时加载到内存中,在操作系统的调度下,可以实现并发地执行。这是这样的设计,大大提高了CPU的利用率。进程的出现让每个用户感觉到自己独享CPU,因此,进程就是为了在CPU上实现多道编程而提出的。

    有了进程为什么还要线程?

    进程有很多优点,它提供了多道编程,让我们感觉我们每个人都拥有自己的CPU和其他资源,可以提高计算机的利用率。很多人就不理解了,既然进程这么优秀,为什么还要线程呢?其实,仔细观察就会发现进程还是有很多缺陷的,主要体现在两点上:

    • 进程只能在一个时间干一件事,如果想同时干两件事或多件事,进程就无能为力了。

    • 进程在执行的过程中如果阻塞,例如等待输入,整个进程就会挂起,即使进程中有些工作不依赖于输入的数据,也将无法执行。

    例如,我们在使用qq聊天, qq做为一个独立进程如果同一时间只能干一件事,那他如何实现在同一时刻 即能监听键盘输入、又能监听其它人给你发的消息、同时还能把别人发的消息显示在屏幕上呢?你会说,操作系统不是有分时么?但我的亲,分时是指在不同进程间的分时呀, 即操作系统处理一会你的qq任务,又切换到word文档任务上了,每个cpu时间片分给你的qq程序时,你的qq还是只能同时干一件事呀。

    再直白一点, 一个操作系统就像是一个工厂,工厂里面有很多个生产车间,不同的车间生产不同的产品,每个车间就相当于一个进程,且你的工厂又穷,供电不足,同一时间只能给一个车间供电,为了能让所有车间都能同时生产,你的工厂的电工只能给不同的车间分时供电,但是轮到你的qq车间时,发现只有一个干活的工人,结果生产效率极低,为了解决这个问题,应该怎么办呢?。。。。没错,你肯定想到了,就是多加几个工人,让几个人工人并行工作,这每个工人,就是线程!

    什么是线程(thread)?

    线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务

    进程与线程的区别?

    1. Threads share the address space of the process that created it; processes have their own address space.
    2. Threads have direct access to the data segment of its process; processes have their own copy of the data segment of the parent process.
    3. Threads can directly communicate with other threads of its process; processes must use interprocess communication to communicate with sibling processes.
    4. New threads are easily created; new processes require duplication of the parent process.
    5. Threads can exercise considerable control over threads of the same process; processes can only exercise control over child processes.
    6. Changes to the main thread (cancellation, priority change, etc.) may affect the behavior of the other threads of the process; changes to the parent process does not affect child processes.

    Python GIL(Global Interpreter Lock)  

    无论你启多少个线程,你有多少个cpu, Python在执行的时候会淡定的在同一时刻只允许一个线程运行。

    首先需要明确的一点是GIL并不是Python的特性,它是在实现Python解析器(CPython)时所引入的一个概念。就好比C++是一套语言(语法)标准,但是可以用不同的编译器来编译成可执行代码。有名的编译器例如GCC,INTEL C++,Visual C++等。Python也一样,同样一段代码可以通过CPython,PyPy,Psyco等不同的Python执行环境来执行。像其中的JPython就没有GIL。然而因为CPython是大部分环境下默认的Python执行环境。所以在很多人的概念里CPython就是Python,也就想当然的把GIL归结为Python语言的缺陷。所以这里要先明确一点:GIL并不是Python的特性,Python完全可以不依赖于GIL

    这篇文章透彻的剖析了GIL对python多线程的影响,强烈推荐看一下:http://www.dabeaz.com/python/UnderstandingGIL.pdf 

    Python threading模块

    #Author:Ivor
    import threading
    import time
    def run(n):
        print("task---start,",n)
        time.sleep(1)
        print("task---end",n,threading.current_thread())
    res_list = []
    start_time = time.time()
    
    #Starting Multiple threads
    for i in range(50):
        t = threading.Thread(target=run,args=("t %s" % i,))
        #set child threads to daemon threads
        t.setDaemon(True)
        t.start()
        res_list.append(t)
    
    #Main Thread waiting for the child threads
    for r in res_list:
        r.join()
    
    print("current thread",threading.current_thread())
    print("Running time = ",time.time() - start_time)
    
    import threading
    
    class MyThread(threading.Thread):
        def __init__(self, num):
            threading.Thread.__init__(self)
            self.num = num
    
        def run(self):  # 定义每个线程要运行的函数
            print("running on number:%s" % self.num)
            time.sleep(3)
    
    if __name__ == '__main__':
        t1 = MyThread(1)
        t2 = MyThread(2)
        t1.start()
        t2.start()
    View Code

    线程锁(互斥锁Mutex)

    #Authon Ivor
    import time
    import threading
    
    def addNum():
        global num  # 在每个线程中都获取这个全局变量
        lock.acquire()
        num -= 1  # 对此公共变量进行-1操作
        lock.release()
    num = 100  # 设定一个共享变量
    thread_list = []
    lock = threading.Lock()
    for i in range(100):
        t = threading.Thread(target=addNum)
        t.start()
        thread_list.append(t)
    for t in thread_list:  # 等待所有线程执行完毕
        t.join()
    
    print('final num:', num)
    View Code

    RLock(递归锁)

    #Authon Ivor
    
    import threading, time
    
    def run1():
        print("grab the first part data")
        lock.acquire()
        global num
        num += 1
        lock.release()
        return num
    
    def run2():
        print("grab the second part data")
        lock.acquire()
        global num2
        num2 += 1
        lock.release()
        return num2
    
    def run3():
        lock.acquire()
        res = run1()
        print('--------between run1 and run2-----')
        res2 = run2()
        lock.release()
        print(res, res2)
    
    num, num2 = 0, 0
    
    lock = threading.RLock() #must be use RLock
    # lock = threading.Lock()
    for i in range(10):
        t = threading.Thread(target=run3)
        t.start()
    
    while threading.active_count() != 1:
        print(threading.active_count())
    else:
        print('----all threads done---')
        print(num, num2)
    View Code

    Semaphore(信号量)

    #Authon Ivor
    import threading
    import time
    
    def run(n):
        semaphore.acquire()
        print(n)
        time.sleep(1)
        semaphore.release()
    
    neq = threading.Semaphore(5)
    semaphore = threading.BoundedSemaphore(5)
    for i in range(10):
        t = threading.Thread(target=run,args=(i,))
        t.start()
    View Code

    Events

    #Authon Ivor
    import threading
    import time
    
    def light():
        count = 0
        #initialize signal
        cond.set()
        while True:
            if count > 5 and count < 10:
                #clear signal
               cond.clear()
               print("33[41;1mRed light33[;0m")
            elif count > 10:
                #set signal
                cond.set()
                count = 0
            else:
                print("33[42;1mGreen light33[;0m")
            count += 1
            time.sleep(1)
    
    def car():
        while True:
            time.sleep(1)
            if cond.is_set():
                print("Car gogo...")
            else:
                print("Car stop...")
                #hang on the thread
                cond.wait()
    
    cond = threading.Event()
    l = threading.Thread(target=light)
    c = threading.Thread(target=car)
    l.start()
    c.start()
    View Code

    不得不提的消息队列

    Queue

    #Authon Ivor
    import threading
    import queue
    
    def producer():
        for i in range(10):
            q.put("骨头 %s" % i)
        print("开始等待所有的骨头被取走...")
        q.join()
        print("所有的骨头被取完了...")
    
    def consumer(n):
        while q.qsize() > 0:
            print("%s 取到" % n, q.get())
            q.task_done()  # 告知这个任务执行完了
    
    q = queue.Queue()
    p = threading.Thread(target=producer)
    p.start()
    c1 = consumer("李闯")
    
    import time,random
    import queue,threading
    
    
    def Producer(name):
      count = 0
      while count <20:
        time.sleep(random.randrange(3))
        q.put(count)
        print('Producer %s has produced %s baozi..' %(name, count))
        count +=1
    
    def Consumer(name):
      count = 0
      while count <20:
        time.sleep(random.randrange(4))
        if not q.empty():
            data = q.get()
            print(data)
            print('33[32;1mConsumer %s has eat %s baozi...33[0m' %(name, data))
        else:
            print("-----no baozi anymore----")
        count +=1
    
    q = queue.Queue()
    p1 = threading.Thread(target=Producer, args=('A',))
    c1 = threading.Thread(target=Consumer, args=('B',))
    p1.start()
    c1.start()
    View Code

    还有一个实现自动化运维的模块

    Pamamiko

    SFTP

    #Authon Ivor
    import paramiko
    #创建一个连接
    conn = paramiko.Transport(('10.0.2.57',22))
    conn.connect(username='root',password='test83@123')
    #通过连接实例,创建一个FTPClient实例
    sftp = paramiko.SFTPClient.from_transport(conn)
    #上传动作
    # sftp.put('D:\test.xls','/tmp/test.xls')
    #下载动作
    # sftp.get('/tmp/test.xls','D:\test.xls')
    conn.close()
    
    #Author:Ivor
    import paramiko
    
    private_key = paramiko.RSAKey.from_private_key_file('/home/auto/.ssh/id_rsa')
    transport = paramiko.Transport(('hostname', 22))
    transport.connect(username='wupeiqi', pkey=private_key)
    sftp = paramiko.SFTPClient.from_transport(transport)
    
    sftp.put('/tmp/location.py', '/tmp/test.py')
    
    sftp.get('remove_path', 'local_path')
    transport.close()
    View Code

    SSH

    #Authon Ivor
    import paramiko
    #创建SSH实例
    ssh = paramiko.SSHClient()
    #设置不在known_host的主机
    ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    #建立连接
    ssh.connect(hostname="10.0.2.57",port=22,username="root:",password="test83@123")
    #执行命令,返回标准输入输出错误
    stdin, stdout, stderr = ssh.exec_command("df")
    #读取结果
    result = stdout.read()
    print(result.decode())
    #关闭连接
    ssh.close()
    
    
    #Author:Ivor
    #######
    #funtion 1
    #######
    import paramiko
    private_key = paramiko.RSAKey.from_private_key_file('id_rsa')
    
    ssh = paramiko.SSHClient()
    
    ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    
    ssh.connect(hostname='59.110.23.110', port=22, username='root', pkey=private_key)
    
    stdin, stdout, stderr = ssh.exec_command('df')
    
    result = stdout.read()
    print(result.decode())
    ssh.close()
    
    ########
    #funtion 2
    ########
    import paramiko
    from io import StringIO
    key = '''XXX
    -----END RSA PRIVATE KEY-----'''
    private_key = paramiko.RSAKey(file_obj=StringIO(key))
    transport = paramiko.Transport((XXXX, 22))
    transport.connect(username='root', pkey=private_key)
    
    ssh = paramiko.SSHClient()
    ssh._transport = transport
    
    stdin, stdout, stderr = ssh.exec_command('df')
    result = stdout.read()
    transport.close()
    print(result)
    View Code
  • 相关阅读:
    让程序的性能提升10倍
    以正确的姿势实现一棵JavaScript菜单树
    利用php数组函数进行函数式编程
    yum安装下的nginx,如何添加模块,和添加第三方模块
    前端面试题 vue
    前端常用面试题目及答案-HTML&CSS篇
    使用after伪类,配合IE的zoom或者overflow清除浮动
    函数式编程
    在CentOS 7上安装Node.js
    node中__dirname、__filename、process.cwd()、process.chdir()表示的路径
  • 原文地址:https://www.cnblogs.com/Darksugar/p/6738454.html
Copyright © 2011-2022 走看看