导航:首页 > 编程语言 > 线程传参python

线程传参python

发布时间:2022-07-06 03:07:44

1. python3 创建线程时不用args传参,执行线程时为什么不是同时执行

在Python多线程下,每个线程的执行方式:
1、获取GIL
2、执行代码直到sleep或者是python虚拟机将其挂起。
3、释放GIL

可见,某个线程想要执行,必须先拿到GIL,我们可以把GIL看作是“通行证”,并且在一个python进程中,GIL只有一个。拿不到通行证的线程,就不允许进入CPU执行。

在Python2.x里,GIL的释放逻辑是当前线程遇见IO操作或者ticks计数达到100(ticks可以看作是Python自身的一个计数器,专门做用于GIL,每次释放后归零,这个计数可以通过
sys.setcheckinterval 来调整),进行释放。

而每次释放GIL锁,线程进行锁竞争、切换线程,会消耗资源。并且由于GIL锁存在,python里一个进程永远只能同时执行一个线程(拿到GIL的线程才能执行),这就是为什么在多核CPU上,python的多线程效率并不高。

那么是不是python的多线程就完全没用了呢?
在这里我们进行分类讨论:
1、CPU密集型代码(各种循环处理、计数等等),在这种情况下,由于计算工作多,ticks计数很快就会达到阈值,然后触发GIL的释放与再竞争(多个线程来回切换当然是需要消耗资源的),所以python下的多线程对CPU密集型代码并不友好。

2、IO密集型代码(文件处理、网络爬虫等),多线程能够有效提升效率(单线程下有IO操作会进行IO等待,造成不必要的时间浪费,而开启多线程能在线程A等待时,自动切换到线程B,可以不浪费CPU的资源,从而能提升程序执行效率)。所以python的多线程对IO密集型代码比较友好。

而在python3.x中,GIL不使用ticks计数,改为使用计时器(执行时间达到阈值后,当前线程释放GIL),这样对CPU密集型程序更加友好,但依然没有解决GIL导致的同一时间只能执行一个线程的问题,所以效率依然不尽如人意。

请注意:多核多线程比单核多线程更差,原因是单核下多线程,每次释放GIL,唤醒的那个线程都能获取到GIL锁,所以能够无缝执行,但多核下,CPU0释放GIL后,其他CPU上的线程都会进行竞争,但GIL可能会马上又被CPU0拿到,导致其他几个CPU上被唤醒后的线程会醒着等待到切换时间后又进入待调度状态,这样会造成线程颠簸(thrashing),导致效率更低

回到最开始的问题:经常我们会听到老手说:“python下想要充分利用多核CPU,就用多进程”,原因是什么呢?

原因是:每个进程有各自独立的GIL,互不干扰,这样就可以真正意义上的并行执行,所以在python中,多进程的执行效率优于多线程(仅仅针对多核CPU而言)。

所以在这里说结论:多核下,想做并行提升效率,比较通用的方法是使用多进程,能够有效提高执行效率

2. 如何向线程传递参数

一、通过构造方法传递数据
在创建线程时,必须要建立一个Thread类的或其子类的实例。因此,我们不难想到在调用start方法之前通过线程类的构造方法将数据传入线程。并将传入的数据使用类变量保存起来,以便线程使用(其实就是在run方法中使用)。下面的代码演示了如何通过构造方法来传递数据:
package mythread;

public class MyThread1 extends Thread
{
private String name;

public MyThread1(String name)
{
this.name = name;
}
public void run()
{
System.out.println("hello " + name);
}
public static void main(String[] args)
{
Thread thread = new MyThread1("world");
thread.start();
}
}
由于这种方法是在创建线程对象的同时传递数据的,因此,在线程运行之前这些数据就就已经到位了,这样就不会造成数据在线程运行后才传入的现象。如果要传递更复杂的数据,可以使用集合、类等数据结构。使用构造方法来传递数据虽然比较安全,但如果要传递的数据比较多时,就会造成很多不便。由于Java没有默认参数,要想实现类似默认参数的效果,就得使用重载,这样不但使构造方法本身过于复杂,又会使构造方法在数量上大增。因此,要想避免这种情况,就得通过类方法或类变量来传递数据。
二、通过变量和方法传递数据
向对象中传入数据一般有两次机会,第一次机会是在建立对象时通过构造方法将数据传入,另外一次机会就是在类中定义一系列的public的方法或变量(也可称之为字段)。然后在建立完对象后,通过对象实例逐个赋值。下面的代码是对MyThread1类的改版,使用了一个setName方法来设置name变量:
package mythread;

public class MyThread2 implements Runnable
{
private String name;

public void setName(String name)
{
this.name = name;
}
public void run()
{
System.out.println("hello " + name);
}
public static void main(String[] args)
{
MyThread2 myThread = new MyThread2();
myThread.setName("world");
Thread thread = new Thread(myThread);
thread.start();
}
}
【注】:本文转自网络。

3. python多线程thread.start_new_thread传参的问题

因为thread.start_new_thread(ssh_cmd,(3,))开的线程会和主线程一起结束,所以等不到执行print number 程序就结束了

4. Python 多线程传参问题

下面是从python threading模块摘录下来的

class threading.Thread(group=None, target=None,
name=None, args=(), kwargs={})

args is the argument tuple for the target invocation. Defaults to
().

kwargs is a dictionary of keyword arguments for the target
invocation. Defaults to {}.

简单的说就是,线程函数的参数要么是tuple类型要么是dict类型,既然python文档上已经规定好了,那么就是不能变了,除非重大的版本升级,弃用现在这种方式,不过这是不可能的,再者可以查看threading.Thread类的初始化代码

classThread(_Verbose):
def__init__(self,group=None,target=None,name=None,
args=(),kwargs=None,verbose=None):
assertgroupisNone,"groupargumentmustbeNonefornow"
_Verbose.__init__(self,verbose)
ifkwargsisNone:
kwargs={}
self.__target=target
self.__name=str(nameor_newname())
self.__args=args
self.__kwargs=kwargs
self.__daemonic=self._set_daemon()
self.__ident=None
self.__started=Event()
self.__stopped=False
self.__block=Condition(Lock())
self.__initialized=True
#sys.
#sys.exc_
self.__stderr=_sys.stderr

看到上面的args和kwargs的赋值情况吗,你不能像**kwargs这样来传参的。

从上面来看,你要使用多线程你就必须遵守这个约定,线程函数参数要么是tuple,要么是字典,没办法改进。非要改进那就是使用全局变量,不用传参,但是如果是这样的话会涉及到线程安全的问题或者叫数据同步问题,如果不加锁或者其他互斥量的话这个问题会很严重。所以还是遵守规定吧

5. python多线程 怎么传送多个参数

importthreadpool
importtime

defMain_Def(par1,par2,par3):
print"par1=%s,par2=%s,par3=%s"%(par1,par2,par3)


if__name__=='__main__':
#方法1
list_var1=['1','2','3']
list_var2=['4','5','6']
par_list=[(list_var1,None),(list_var2,None)]
#方法2
#dict_var1={'par1':'1','par2':'2','par3':'3'}
#dict_var2={'par1':'4','par2':'5','par3':'6'}
#par_list=[(None,dict_var1),(None,dict_var2)]

pool=threadpool.ThreadPool(2)
requests=threadpool.makeRequests(Main_Def,par_list)
[pool.putRequest(req)forreqinrequests]
time.sleep(1)
pool.wait()

6. python中使用_thread模块创建进程怎么使用可选参数

_thread.start_new_thread(fun1,('thread_1', 4, '参数3'))
_thread.start_new_thread(fun2,('thread_1', 2, '参数3'))

7. python 已经启动的线程 怎么往里面传参数

把参数放到Queue里,线程从Queue里获得参数,Queue是线程安全的

8. python子线程如何发运行结果传给主线程

可以这样 子进程把信息写入文件,然后发信号给父进程,父进程收到信号后读文件。

9. Python多线程的一些问题

python提供了两个模块来实现多线程thread 和threading ,thread 有一些缺点,在threading 得到了弥补,为了不浪费你和时间,所以我们直接学习threading 就可以了。
继续对上面的例子进行改造,引入threadring来同时播放音乐和视频:
#coding=utf-8import threadingfrom time import ctime,sleepdef music(func): for i in range(2): print "I was listening to %s. %s" %(func,ctime())
sleep(1)def move(func): for i in range(2): print "I was at the %s! %s" %(func,ctime())
sleep(5)

threads = []
t1 = threading.Thread(target=music,args=(u'爱情买卖',))
threads.append(t1)
t2 = threading.Thread(target=move,args=(u'阿凡达',))
threads.append(t2)if __name__ == '__main__': for t in threads:
t.setDaemon(True)
t.start() print "all over %s" %ctime()

import threading
首先导入threading 模块,这是使用多线程的前提。

threads = []
t1 = threading.Thread(target=music,args=(u'爱情买卖',))
threads.append(t1)
创建了threads数组,创建线程t1,使用threading.Thread()方法,在这个方法中调用music方法target=music,args方法对music进行传参。 把创建好的线程t1装到threads数组中。
接着以同样的方式创建线程t2,并把t2也装到threads数组。

for t in threads:
t.setDaemon(True)
t.start()
最后通过for循环遍历数组。(数组被装载了t1和t2两个线程)

setDaemon()
setDaemon(True)将线程声明为守护线程,必须在start() 方法调用之前设置,如果不设置为守护线程程序会被无限挂起。子线程启动后,父线程也继续执行下去,当父线程执行完最后一条语句print "all over %s" %ctime()后,没有等待子线程,直接就退出了,同时子线程也一同结束。

start()
开始线程活动。

运行结果:
>>> ========================= RESTART ================================
>>> I was listening to 爱情买卖. Thu Apr 17 12:51:45 2014 I was at the 阿凡达! Thu Apr 17 12:51:45 2014 all over Thu Apr 17 12:51:45 2014

从执行结果来看,子线程(muisc 、move )和主线程(print "all over %s" %ctime())都是同一时间启动,但由于主线程执行完结束,所以导致子线程也终止。

继续调整程序:
...if __name__ == '__main__': for t in threads:
t.setDaemon(True)
t.start()

t.join() print "all over %s" %ctime()

我们只对上面的程序加了个join()方法,用于等待线程终止。join()的作用是,在子线程完成运行之前,这个子线程的父线程将一直被阻塞。
注意: join()方法的位置是在for循环外的,也就是说必须等待for循环里的两个进程都结束后,才去执行主进程。
运行结果:
>>> ========================= RESTART ================================
>>> I was listening to 爱情买卖. Thu Apr 17 13:04:11 2014 I was at the 阿凡达! Thu Apr 17 13:04:11 2014I was listening to 爱情买卖. Thu Apr 17 13:04:12 2014I was at the 阿凡达! Thu Apr 17 13:04:16 2014all over Thu Apr 17 13:04:21 2014

从执行结果可看到,music 和move 是同时启动的。
开始时间4分11秒,直到调用主进程为4分22秒,总耗时为10秒。从单线程时减少了2秒,我们可以把music的sleep()的时间调整为4秒。
...def music(func): for i in range(2): print "I was listening to %s. %s" %(func,ctime())
sleep(4)
...

子线程启动11分27秒,主线程运行11分37秒。
虽然music每首歌曲从1秒延长到了4 ,但通多程线的方式运行脚本,总的时间没变化。

10. python 像这样定义多线程的类在调用时怎么把调用父类的参数传递给子函数

你已经实现了啊。在__init__初始化参数里,将参数传递进去。

另外因为线程工作在主程序同一个空间里,所以可以用全局变量传递。比如定义一个global v,然后在主程序里设置好。
再在线程里用global v来引用。

如果在线程运行当中,动态的改参数。可以象是这里的thread_stop设置。由主进程与从进程单对单的传递信号。

另外还可以通过队列。这个好处是有一个锁,可以全局使用。

此外你还可以引入一个消息管理器。各个线程与主进程直接通过消息传递变量。

进程之间也可以通过共享内存来实现RPC通信,就是交换数据。

线程处理完的数据,如果主程序想处理。可以这样。让线程通过全局变量,通过队列传回来。

不过主进程通常还有一个任务,就是监督线程的完成退处,并管理线程中止信号。

比如你这个程序少了一个
thread.join() 这里的join可以加一个timeout,当超时时,主进程就可以脱身出来,做一些其它的事情,比如处理返回数值。 如果线程通过一个数组变量将状态传回主进程。这样轮洵子线程状态会比join的效率更高。

你这个程序里用文件传递也不是不可以。这是一个很好思路。当你传递变量困难时,可以用文件。或者是数据库。

阅读全文

与线程传参python相关的资料

热点内容
自己购买云主服务器推荐 浏览:422
个人所得税java 浏览:761
多余的服务器滑道还有什么用 浏览:192
pdf劈开合并 浏览:28
不能修改的pdf 浏览:752
同城公众源码 浏览:489
一个服务器2个端口怎么映射 浏览:298
java字符串ascii码 浏览:79
台湾云服务器怎么租服务器 浏览:475
旅游手机网站源码 浏览:332
android关联表 浏览:946
安卓导航无声音怎么维修 浏览:333
app怎么装视频 浏览:431
安卓系统下的软件怎么移到桌面 浏览:96
windows拷贝到linux 浏览:772
mdr软件解压和别人不一样 浏览:904
单片机串行通信有什么好处 浏览:340
游戏开发程序员书籍 浏览:860
pdf中图片修改 浏览:288
汇编编译后 浏览:491