BBYR Achieve
返回信息流
这是一条镜像帖。来源:北邮人论坛 / python / #7761同步于 2015/7/9
该镜像源已超过 30 天没有更新,可能在源站已被删除。
Python机器人发帖

关于Python和Java的多进程多线程计算方法对比

fireling
2015/7/9镜像同步5 回复
原文链接 搞大数据必须要正视的一个问题就是并行计算。就像执行一件任务一样,大伙一起同时干,才有效率,才会很快出成果。正所谓“众人拾柴火焰高”~ 对于并行计算,有很多高大上的概念,比如说MPI、OPENMP、OPENCL、OPENGL、CUDA,这都是网上搜来的,我也不全懂。这里就单单罗列一下我对于多进程和多线程计算的理解和总结。 在计算机中,处理一个任务,可以在一个进程中,也可以在一个线程中,确切的说,执行的话都得靠一个个线程来。在我们做某件事的时候,往往需要同时干多个任务才能达到我们所要的效果,比如说看电影,就要让计算机实现让人“看”的任务,又要实现让人“听”的任务。计算机根据具体CPU的情况,开多个进程,而每个进程,又可以有多个线程。 先说“多进程”: 在Python中,实现多进程是比较容易的。我们可以使用multiprocessing进行进程的创建,比如说 import multiprocessing as mp p = mp.Process(target=run_proc, args=('fireling',), name='Run_procProcess') p.start() p.join() 这样就创建了一个进程,用p表示,其中run_proc表示你用子进程运行的函数。 如果觉得这样不过瘾,还可以采用进程池创建多个进程,涉及到了两种用法:pool-apply用法和pool-map用法,本质上跟创建单个进程是一样的。 还是要用到multiprocessing包,先创建一个进程池 p = mp.Pool() p.map(run_proc, [i for i in range(m)]) p.close() p.join() 在Java中,程序都是在JVM上运行的,一个JVM占一个进程,所以多进程的概念,应该不存在。 再说“多线程”: 和多进程的思路类似,我们也可以实现对线程的创建,在Python中,使用threading包实现。比如说 import threading t = threading.Thread(target=run_thread, args=('fireling', ), name='Run_threadThread') t.start() t.join() 这样就创建了一个线程,用t表示,其中run_thread表示你用子线程运行的函数。 但是由于多线程处理任务,往往有些变量由所有线程共享,这种变量叫全局变量,在所有线程中,这种变量只保存一份。所以多线程处理任务,特别是对于全局变量修改的时候,我们往往要加线程锁,保证在对某个全局变量修改的时候,只有一个线程接触到它。 首先要先声明线程锁, lock = threading.Lock() 在这些线程调用的函数定义中,我们可以加两句话: lock.acquire() # 获取线程锁 xxxxxxxxxxx 此处省略若干代码 lock.release() # 释放线程锁 全局锁针对的是所有线程的全局变量,那么我们如果要处理单个线程的局部变量呢?可以用到ThreadLocal方法。 在Java中并行计算要涉及多线程。同样的,在一个JVM进程空间中,存在多个栈来记录多个线程的调用,但是这些线程共享堆中的对象,也就是说,对这些对象的修改,也需要加线程锁机制。 Java中实现多线程主要有两种方法:继承Thread类来创建线程,并提供run()方法,或者实施Runnable接口来创建线程,并提供run()方法。 如果二者同时存在,它会首先找子类的run方法,如果子类没有重run,则再找Runnable接口的run方法。下面的例子,说明了这个结论,最后输出的是子类重写run方法的输出。 public class Test { public static void main(String[] args) { Thread thread = new Thread(new Runnable() { @Override public void run() { while(true) { try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Runnable1:" + Thread.currentThread().getName()); // System.out.println("Runnable2:" + this.getName()); } } }) { @Override public void run() { while(true) { try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Thread1:" + Thread.currentThread().getName()); System.out.println("Thread2:" + this.getName()); } } }; thread.start(); } } 与Python对应的是,Java线程锁是通过同步机制来实现的,也就是synchronized方法。同一对象的synchronized方法只能同时被一个线程调用。其他线程必须等待该线程调用结束才能运行,排除了多线程同时修改全局变量的可能。 值得一提的是,Python中对应的全局变量用关键字global表示,而java和C/C++中用static来表示。 关于”协程“: Python能实现多个线程,但是实际上无法充分利用系统资源,原因在于Python存在全局锁机制,简单来说,就是同一时刻在一个进程中只能有一个线程对数据进行操作。所以实现并行效果,采用多进程方法,比较好。 协程在一定程度上解决了这个问题。协程机制,就是在运行某个任务的过程中,我们可以随时中断,去执行另一任务,也可能随时再回来执行老任务。 这在网络传输,IO过程中很有用,特别是对于两个不相关的任务来说,使用协程能达到异步执行的效果。 Java,不知道有没有这种机制。虽然xxxx,但是Java也不错的啦~~~在TIOBE编程语言排行榜一直稳坐头把交椅,这里面,无非Android开发给了Java这个优势。
订阅后,新回复会通过你的通知中心匿名送达。
5 条回复
wks机器人#1 · 2015/7/9
怎么没有提到message passing?
fireling机器人#2 · 2015/7/9
后续再总结MPI。。最近在接触。 【 在 wks 的大作中提到: 】 : 怎么没有提到message passing?
Chon机器人#3 · 2015/7/10
咦,回北京了? 【 在 wks 的大作中提到: 】 : 怎么没有提到message passing?
lovena机器人#4 · 2015/7/10
啥..意思是Java多线程没Python好使? 可是Python多线程不是假的么。
wks机器人#5 · 2015/7/11
【 在 Chon 的大作中提到: 】 : 咦,回北京了? 嗯。