python 多线程

简介: python 多线程

python 多线程

文章目录

1. 多线程

多线程类似于同时执行多个不同程序,多线程运行有如下优点:


·可以把运行时间长的任务放到后台去处理。

·用户界面可以更加吸引人,比如用户点击了一个按钮去触发某些事件的处理, 可以弹出一个进度条来显示处理的进度。

·程序的运行速度可能加快。

·在一些需要等待的任务实现上,如用户输入、文件读写和网络收发数据等,线

程就比较有用了。在这种情况下我们可以释放一些珍贵的资源,如内存占用等。

Python的标准库提供了两个模块:thread和 threading,thread是低级模 块,threading是高级模块,对thread进行了封装。绝大多数情况下,我们只需要 使用threading这个高级模块。

2. 用threading模块创建多线程

threading模块一般通过两种方式创建多线程:第一种方式是把一个函数传入 并创建Thread实例,然后调用start方法开始执行;第二种方式是直接从 threading.Thread继承并创建线程类,然后重写__init__方法和run方法。

首先介绍第一种方法,通过一个简单例子演示创建多线程的流程,程序如下:

#coding:utf-8
import random     
import time, threading     
# 新线程执行的代码:     
def thread_run(urls):        
    print 'Current %s is running...' % threading.current_thread().name        
    for url in urls:                
        print '%s ---->>> %s' % (threading.current_thread().name,url)                
        time.sleep(random.random())        
    print '%s ended.' % threading.current_thread().name          
print '%s is running...' % threading.current_thread().name     
t1 = threading.Thread(target=thread_run, name='Thread_1',args=(['url_1','url_2','url_3'],))     
t2 = threading.Thread(target=thread_run, name='Thread_2',args=(['url_4','url_5','url_6'],))     
t1.start()     
t2.start()     
t1.join()     
t2.join()     
print '%s ended.' % threading.current_thread().name
$ python thr1.py
MainThread is running...
Current Thread_1 is running...
Thread_1 ---->>> url_1
Current Thread_2 is running...
Thread_2 ---->>> url_4
Thread_2 ---->>> url_5
Thread_1 ---->>> url_2
Thread_1 ---->>> url_3
Thread_2 ---->>> url_6
Thread_2 ended.
Thread_1 ended.
MainThread ended.

第二种方式从threading.Thread继承创建线程类,下面将方法一的程序进行重 写,程序如下:

#coding:utf-8
import random     
import threading     
import time     
class myThread(threading.Thread):        
      def __init__(self,name,urls):                
         threading.Thread.__init__(self,name=name)                
         self.urls = urls             
      def run(self):                
          print 'Current %s is running...' % threading.current_thread().name                
          for url in self.urls:                        
              print '%s ---->>> %s' % (threading.current_thread().name,url)                        
              time.sleep(random.random())                
          print '%s ended.' % threading.current_thread().name     
print '%s is running...' % threading.current_thread().name     
t1 = myThread(name='Thread_1',urls=['url_1','url_2','url_3'])     
t2 = myThread(name='Thread_2',urls=['url_4','url_5','url_6'])     
t1.start()     
t2.start()     
t1.join()     
t2.join()

3. 线程同步

如果多个线程共同对某个数据修改,则可能出现不可预料的结果,为了保证数 据的正确性,需要对多个线程进行同步。使用Thread对象的Lock和RLock可以实现 简单的线程同步,这两个对象都有acquire方法和release方法,对于那些每次只允 许一个线程操作的数据,可以将其操作放到acquire和release方法之间。

对于Lock对象而言,如果一个线程连续两次进行acquire操作,那么由于第一 次acquire之后没有release,第二次acquire将挂起线程。这会导致Lock对象永远 不会release,使得线程死锁。RLock对象允许一个线程多次对其进行acquire操 作,因为在其内部通过一个counter变量维护着线程acquire的次数。而且每一次的 acquire操作必须有一个release操作与之对应,在所有的release操作完成之后, 别的线程才能申请该RLock对象。下面通过一个简单的例子演示线程同步的过程:

import threading
mylock = threading.RLock()     
num=0     
class myThread(threading.Thread):        
      def __init__(self, name):                
          threading.Thread.__init__(self,name=name)             
      def run(self):                
          global num                
          while True:                        
                mylock.acquire()                        
                print '%s locked, Number: %d'%(threading.current_thread().name, num)                        
                if num>=4:                                
                   mylock.release()                                
                   print '%s released, Number: %d'%(threading.current_thread().name, num)
                   break                        
                num+=1                        
                print '%s released, Number: %d'%(threading.current_thread().name, num)                        
                mylock.release()               
if __name__== '__main__':        
   thread1 = myThread('Thread_1')        
   thread2 = myThread('Thread_2')        
   thread1.start()        
   thread2.start()
$ python th3.py
Thread_1 locked, Number: 0
Thread_1 released, Number: 1
Thread_1 locked, Number: 1
Thread_1 released, Number: 2
Thread_1 locked, Number: 2
Thread_1 released, Number: 3
Thread_1 locked, Number: 3
Thread_1 released, Number: 4
Thread_1 locked, Number: 4
Thread_1 released, Number: 4
Thread_2 locked, Number: 4
Thread_2 released, Number: 4

4 全局解释器锁(GIL)

在Python的原始解释器CPython中存在着GIL(Global Interpreter Lock, 全局解释器锁),因此在解释执行Python代码时,会产生互斥锁来限制线程对共享 资源的访问,直到解释器遇到I/O操作或者操作次数达到一定数目时才会释放GIL。 由于全局解释器锁的存在,在进行多线程操作的时候,不能调用多个CPU内核,只能 利用一个内核,所以在进行CPU密集型操作的时候,不推荐使用多线程,更加倾向于 多进程。那么多线程适合什么样的应用场景呢?对于IO密集型操作,多线程可以明 显提高效率,例如Python爬虫的开发,绝大多数时间爬虫是在等待socket返回数 据,网络IO的操作延时比CPU大得多。

参考:


gevent调度流程解析

Python process, thread and coroutine

Difference between Multi-Processing, Multi-threading and Coroutine

Choosing between Python threads vs coroutines vs processes

python process thread coroutine

Combining Coroutines with Threads and Processes


相关文章
|
18天前
|
安全 数据处理 开发者
Python中的多线程编程:从入门到精通
本文将深入探讨Python中的多线程编程,包括其基本原理、应用场景、实现方法以及常见问题和解决方案。通过本文的学习,读者将对Python多线程编程有一个全面的认识,能够在实际项目中灵活运用。
|
12天前
|
Java Unix 调度
python多线程!
本文介绍了线程的基本概念、多线程技术、线程的创建与管理、线程间的通信与同步机制,以及线程池和队列模块的使用。文章详细讲解了如何使用 `_thread` 和 `threading` 模块创建和管理线程,介绍了线程锁 `Lock` 的作用和使用方法,解决了多线程环境下的数据共享问题。此外,还介绍了 `Timer` 定时器和 `ThreadPoolExecutor` 线程池的使用,最后通过一个具体的案例展示了如何使用多线程爬取电影票房数据。文章还对比了进程和线程的优缺点,并讨论了计算密集型和IO密集型任务的适用场景。
31 4
|
19天前
|
Python
Python中的多线程与多进程
本文将探讨Python中多线程和多进程的基本概念、使用场景以及实现方式。通过对比分析,我们将了解何时使用多线程或多进程更为合适,并提供一些实用的代码示例来帮助读者更好地理解这两种并发编程技术。
|
26天前
|
Java Python
python知识点100篇系列(16)-python中如何获取线程的返回值
【10月更文挑战第3天】本文介绍了两种在Python中实现多线程并获取返回值的方法。第一种是通过自定义线程类继承`Thread`类,重写`run`和`join`方法来实现;第二种则是利用`concurrent.futures`库,通过`ThreadPoolExecutor`管理线程池,简化了线程管理和结果获取的过程,推荐使用。示例代码展示了这两种方法的具体实现方式。
python知识点100篇系列(16)-python中如何获取线程的返回值
|
1月前
|
数据挖掘 程序员 调度
探索Python的并发编程:线程与进程的实战应用
【10月更文挑战第4天】 本文深入探讨了Python中实现并发编程的两种主要方式——线程和进程,通过对比分析它们的特点、适用场景以及在实际编程中的应用,为读者提供清晰的指导。同时,文章还介绍了一些高级并发模型如协程,并给出了性能优化的建议。
29 3
|
1月前
|
并行计算 安全 Java
Python 多线程并行执行详解
Python 多线程并行执行详解
63 3
|
29天前
|
网络协议 安全 Java
难懂,误点!将多线程技术应用于Python的异步事件循环
难懂,误点!将多线程技术应用于Python的异步事件循环
51 0
|
1月前
|
安全 Java 数据库连接
Python多线程编程:竞争问题的解析与应对策略
Python多线程编程:竞争问题的解析与应对策略
21 0
|
1月前
|
设计模式 监控 安全
Python多线程编程:特性、挑战与最佳实践
Python多线程编程:特性、挑战与最佳实践
35 0
|
1月前
|
安全 Java 数据库连接
Python多线程编程:竞争问题的解析与应对策略【2】
Python多线程编程:竞争问题的解析与应对策略【2】
22 0
下一篇
无影云桌面