python多线程thread,threading哪个好

thread与threading的区别

thread模块提供了基本的线程和锁定支持;而threading模块提供了更高级别、功能更全面的线程管理。
应该避免使用thread模块,尽量使用threading模块,原因如下:
(1)threading模块更加先进,有更好的线程支持,并且thread模块中的一些属性会和threading模块有冲突.
(2)thread模块拥有的同步原语很少,而threading模块有很多。
(3)thread模块对于进程何时退出没有控制。当主线程结束时,所有其他线程也都强制结束,不会发出警告或者进行适当的清理。

python下多线程的限制以及多进程中传递参数的方式

python多线程有个全局解释器锁(global interpreter lock),这个锁的意思是任一时间只能有一个线程使用解释器,跟单cpu跑多个程序一个意思,大家都是轮着用的,这叫“并发”,不是“并行”。
多进程间共享数据,可以使用 multiprocessing.Value 和 multiprocessing.Array

python多线程与多进程的区别

在UNIX平台上,当某个进程终结之后,该进程需要被其父进程调用wait,否则进程成为僵尸进程(Zombie)。所以,有必要对每个Process对象调用join()方法 (实际上等同于wait)。对于多线程来说,由于只有一个进程,所以不存在此必要性。
多进程应该避免共享资源。在多线程中,我们可以比较容易地共享资源,比如使用全局变量或者传递参数。在多进程情况下,由于每个进程有自己独立的内存空间,以上方法并不合适。此时我们可以通过共享内存和Manager的方法来共享资源。但这样做提高了程序的复杂度,并因为同步的需要而降低了程序的效率。

串行程序例子

为了更好的了解多线程,首先来看个 串行执行的例子

import time

def loop1():
    print 'start loop1 at ', time.ctime()
    time.sleep(4)
    print 'end loop1 at ', time.ctime()

def loop2():
    print 'start loop2 at ', time.ctime()
    time.sleep(2)
    print 'end loop2 at ', time.ctime()

def main():
    print 'start main at ', time.ctime()
    loop1()
    loop2()
    print 'end main at ', time.ctime()


if __name__ == '__main__':
    main()

这个串行执行的例子,先执行loop1 ,再执行loop2 。

thread.start_new_thread实现多线程

由于使用thread模块时,主线程结束时,所有其他线程也都强制结束。下面例子采取让主线程sleep的方式来保证子线程先完成。

import thread
import time

def loop1():
    print 'start loop1 at ', time.ctime()
    time.sleep(4)
    print 'end loop1 at ', time.ctime()

def loop2():
    print 'start loop2 at ', time.ctime()
    time.sleep(2)
    print 'end loop2 at ', time.ctime()

def main_thread():
    print 'start main at ', time.ctime()
    thread.start_new_thread(loop1, ())
    thread.start_new_thread(loop2, ())
    time.sleep(6)
    print 'All done at ', time.ctime()


if __name__ == '__main__':
    main_thread()

由于loop1和loop2函数过于简单,我们可以预估loop1和loop2的完成时间,然后在main_thread函数直接相加两个时间,同时,在4s时,loop1和loop2都已经执行完了,没有实现多线程的优势。在实际情况中,这种方法是十分不可取的。

使用锁机制实现多线程

import time
import thread

loops = [44, 42]

def loop(nsecs, loopname, lock):
    print 'start ', loopname, ' at: ', time.ctime()
    time.sleep(nsecs)
    print 'end ', loopname, ' at: ', time.ctime()
    lock.release()

def main():
    print 'start main at ', time.ctime()
    # locks保存锁对象的列表
    locks = []
    nloops = range(len(loops))

    for i in nloops:
        lock = thread.allocate()
        lock.acquire()
        locks.append(lock)

    for i in nloops:
        thread.start_new_thread(loop, (loops[i], ('loop' + str(i)), locks[i]))

    for i in nloops:
        while locks[i].locked():
            pass

    print 'All done at: ', time.ctime()


if __name__ == '__main__':
    main()

每个线程将被分配一个已获得的锁。当sleep()的时间到了的时候,释放对应的锁,向主线程表明该线程已完成。
通过使用thread.allocate_lock()函数得到锁对象,然后通过acquire()方法取得(每个锁)。取得锁效果相当于“把锁锁上”。
最后一个循环只是坐在那里等待(暂停主线程),直到所有锁都被释放之后才会继续执行。

Threading模块实现多线程

上边提到,应该使用更高级的threading模块实现多线程,这里研究使用Thread类来实现多线程,threading模块支持守护线程。使用Thread类,有多种创建线程的方法:
(1)创建Thread 的实例,传给它一个函数。
(2)创建Thread 的实例,传给它一个可调用的类实例。
(3)派生Thread 的子类,并创建子类的实例。
Thread类的常用方法:

方法说明
init(group=None, tatget=None, name=None, args=(),kwargs ={}, verbose=None, daemon=None)实例化一个线程对象,需要有一个可调用的target,以及其参数args或kwargs。还可以传递name 或group 参数,不过后者还未实现。此外, verbose 标志也是可接受的。而daemon 的值将会设定thread.daemon 属性/标志
start()开始执行该线程
run()定义线程功能的方法(通常在子类中被应用开发者重写)
join(timeout=None)直至启动的线程终止之前一直挂起;除非给出了timeout(秒),否则会一直阻塞

创建一个Thread的实例,并传给它一个函数

在第3节的多线程例子中,需要自己管理锁来实现多线程,这样其实比较麻烦。使用threading.Thread类时,就省去了锁的管理,实例化Thread(调用Thread())和调用thread.start_new_thread()的最大区别是新线程不会立即开始执行。

from time import ctime
from time import sleep
import threading

sleepsecs = [4, 8]

def loop(loopname, secs):
    print 'start loop',loopname, ' at: ', ctime()
    sleep(secs)
    print 'end loop',loopname, ' at: ', ctime()


if __name__ == '__main__':
    # Thread对象列表
    threads = []

    for i in range(len(sleepsecs)):
        thread = threading.Thread(target=loop, args=(i, sleepsecs[i]))
        threads.append(thread)

    print 'start main at :', ctime()
    # 逐个启动线程
    for i in range(len(sleepsecs)):
        threads[i].start()
        sleep(0.001)

    for i in range(len(sleepsecs)):
        threads[i].join()

    print 'end main at ', ctime()

创建一个Thread的实例,传给它一个可调用的类实例

下面添加一个ThreadFunc类,在实例化Thread类时,实际做了2次实例化,包括Thread和ThreadFunc。
当创建新线程时,Thread 类的代码将调用ThreadFunc 对象,此时会调用call()这个特殊方法。

from time import sleep
from time import ctime
from threading import Thread

class ThreadFunc(object):
    # func: 多线程要执行的函数  该参数就是一个函数对象
    # loopname: 执行函数名称
    # secs: sleep等待时间
    def __init__(self, func, loopname, secs):
        self.func = func
        self.loopname = loopname
        self.secs = secs

    def __call__(self):
        self.func(self.loopname, self.secs)

def loop(loopname, secs):
    print 'start loop ', loopname, ' at: ', ctime()
    sleep(secs)
    print 'end loop ', loopname, ' at: ', ctime()


if __name__ == '__main__':
    threads = []
    secs = [4, 8]

    print 'start main at: ', ctime()
    for i in range(len(secs)):
        thread = Thread(target=ThreadFunc(loop, i, secs[i]))
        threads.append(thread)

    for i in range(len(secs)):
        threads[i].start()
        sleep(0.001)

    for i in range(len(secs)):
        threads[i].join()

    print 'end main at:', ctime()

派生Thread的子类,并创建子类的实例

派生子类时,只需要创建子类的实例即可,不用再创建Thread类实例。需要注意下边2点:
1.MyThread子类的构造函数必须先调用其基类的构造函数。
2.必须在子类中定义run()方法。

from threading import Thread
from time import ctime
from time import sleep

class MyThread(Thread):
    # func:该参数是多线程执行的函数
    # args:func函数的参数列表,多个参数的列表
    # name:名称
    def __init__(self, func, args, name):
        # MyThread子类的构造函数必须先调用其基类的构造函数
        Thread.__init__(self)
        self.func = func
        self.args = args
        self.name = name

    # 必须在子类中定义run()方法
    def run(self):
        self.func(*self.args)

def loop(nloop, secs):
    print 'start loop ', nloop, ' at: ', ctime()
    sleep(secs)
    print 'end loop ', nloop, ' at: ', ctime()


if __name__ == '__main__':
    seconds = [4, 8]
    threads = []
    print 'start main at: ', ctime()

    # 创建线程,但是未启动
    for i in range(len(seconds)):
        thread = MyThread(loop, (i, seconds[i]), '')
        threads.append(thread)

    # 启动线程
    for i in range(len(seconds)):
        threads[i].start()
        sleep(0.001)

    for i in range(len(seconds)):
        threads[i].join()

    print 'end main at: ', ctime()

独立抽象myThread模块

为了应用更加方便,将MyThread类独立抽象出来,后边直接引入就可以使用,并且保存下返回结果,做得更加通用。

from threading import Thread
from time import ctime

class MyThread(Thread):
    def __init__(self, func, args, name):
        Thread.__init__(self)
        self.func = func
        self.args = args
        self.name = name

    def getResult(self):
        return self.res

    def run(self):
        print 'starting ', self.name, ' at: ', ctime()
        self.func(*self.args)
        print 'finish ', self.name , ' at: ', ctime()

阶乘、求和的 多线程实现

为了展示多线程的实现结果,在每次计算的时候,sleep 0.1秒,并试图用多线程优化。

from time import sleep
from time import ctime
from MyThread import MyThread


# 递归斐波那契
def recursion_fib(x):
    sleep(0.1)
    if x < 3:
        return 1
    else:
        return recursion_fib(x-2) + recursion_fib(x-1)

# 递归阶乘
def recursion_multiply(x):
    sleep(0.1)
    if x < 2:
        return 1
    else:
        return x*recursion_multiply(x-1)

# 递归实现时,只需要考虑这个函数在不同条件下的返回值,需要有终止条件
def recursion_sum(x):
    sleep(0.1)
    if x < 2:
        return 1
    else:
        return x+recursion_sum(x-1)


if __name__ == '__main__':
    func_names = ['fib', 'recMul', 'recSum']
    funcs = [recursion_fib, recursion_multiply, recursion_sum]
    threads = []

    print 'start Single Thread -------------------'
    for i in range(len(funcs)):
        print 'start function ', func_names[i], ' at: ', ctime()
        funcs[i](10)
        print 'end function ', func_names[i], ' at: ', ctime()
    print 'end Single Thread -------------------'

    print 'start Multiple Thread -------------------'
    for i in range(len(funcs)):
        thread = MyThread(funcs[i], (10,), func_names[i])
        threads.append(thread)

    for i in range(len(funcs)):
        threads[i].start()
        sleep(0.001)

    for i in range(len(funcs)):
        threads[i].join()
        print threads[i].getResult()

    print 'end Multiple Thread -------------------'

赞(2) 打赏
特别声明:除特殊标注,本站文章均为原创,遵循CC BY-NC 3.0,转载请注明出处。三伏磨 » python多线程thread,threading哪个好

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏