@多线程和多进程是什么?看这篇文章,http://www.cnblogs.com/feichengwulai/articles/3721996.html

@主要模块thread模块,time模块

---模块函数:start_new_thread(func,args),allocate_lock(),exit。

  锁对象有三个方法acquire(),locked(),release()。下面是如何生成锁对象

---thread.allocate_lock()      生成锁对象,注意锁对象和线程是两个完全不同的概念

  lock.acquire()    加锁,加锁后,线程就可以使用锁对象了

  lock.release()    线程调度释放锁对象

---acquire负责加锁,release负责解锁。

  如果锁定了,lock.locked()的状态为true,如果解锁了lock.locked()就是false

---一个使用案例

上边代码中,首先声明一个播放视频函数(playVideo),下边声明一个锁对象,加锁。

下边声明两个新的线程,一个播放图片,播放30次,一个播放声音,播放30次。两个线程都上了锁。

当两者循环完以后,锁对象就会解锁l.release() ,lock.locked()状态就会变成false,就会退出循环。

 

1,什么是单线程?(一个时间点只能做一件事。)

  在好些年前的MS-DOS时代,操作系统处理问题都是单任务的,我想做听音乐和看电影两件事儿,那么一定要先排一下顺序。

(好吧!我们不纠结在DOS时代是否有听音乐和看影的应用。^_^

from time import ctime,sleep

def music():
    for i in range(2):
        print "I was listening to music. %s" %ctime()
        sleep(1)

def move():
    for i in range(2):
        print "I was at the movies! %s" %ctime()
        sleep(5)

if __name__ == '__main__':
    music()
    move()
    print "all over %s" %ctime()

  我们先听了一首音乐,通过for循环来控制音乐的播放了两次,每首音乐播放需要1秒钟,sleep()来控制音乐播放的时长。接着我们又看了一场电影,每一场电影需要5秒钟,因为太好看了,所以我也通过for循环看两遍。在整个休闲娱乐活动结束后,我看了一下当前时间,差不多该睡觉了。

  运行结果:

>>=========================== RESTART ================================
>>> 
I was listening to music. Thu Apr 17 10:47:08 2014
I was listening to music. Thu Apr 17 10:47:09 2014
I was at the movies! Thu Apr 17 10:47:10 2014
I was at the movies! Thu Apr 17 10:47:15 2014
all over Thu Apr 17 10:47:20 2014

 

2,什么是多线程?同时做多件事情,例如同时执行多个方法。(@注意thread和threading用法是不同的?下边案例用的是threading方法)

  科技在发展,时代在进步,我们的CPU也越来越快,CPU抱怨,P大点事儿占了我一定的时间,其实我同时干多个活都没问题的;于是,操作系统就进入了多任务时代。我们听着音乐玩着其他程序不在是梦想

  python提供了两个模块来实现多线程thread threading ,thread 有一些缺点,在threading 得到了弥补,为了不浪费你和时间,所以我们直接学习threading 就可以了。

  ---threading模块建立在thread模块之上,可以更容易地管理多个执行线程。通过使用线程,程序可以在同一个进程空间并发地运行多个操作。threading模块建立在thread的底层特性基础之上,可以更容易地完成线程处理。

  (1),第一个简单的实例

   import threading

   def worker(num):
        print 'worker:%s' %num
        return

     threads=[]
        for i in range(5):
        t=threading.Thread(target=worker, args=(i, ))  //任何类型的对象,都可以作为参数传递到线程。联系C#中的多线程一起记忆
          threads.append(t)
          t.start()

  ---输出5行

  worker:0
    worker:1
  worker:2
  worker:3
  worker:4
  (2),确定当前线程

  使用参数来标识或命名线程很麻烦,也没有必要。每个Thread实例都有一个名称,它有一个默认值,可以在创建线程时改变。如果服务器进程由处理不同操作的多个服务线程构成,在这样的服务器进程中,对线程命名很有用

   print threading.currentThread().getName()  //这段代码就能获取当前线程名,例如在上边worker方法中,加入这段代码,会输出Thread-5类似的线程名。

  print threading.currentThread().getName(), num  //这后面可以加上参数,就会输出Thread-1 0

  print threading.currentThread().getName(), 'starting'  //后面可以加上字符串,就会输出Thread-1 starting

  (3),守护和非守护线程(守护线程的作用就是用一种容易的方法来中断线程!!!,具体用法,视情况而定。)

  ---在Java中也有两类线程:User Thread(用户线程)、Daemon Thread(守护线程)

  守护线程的概念有点不同于Linux环境下的概念,可能是我没理解,但是这个概念和Java里的守护线程一样

    守护线程主线程退出后也会随着退出,非守护线程(普通线程)则不会什么意思呢?看下边:

 

    * 对于普通线程,如果线程的任务没有结束,主线程不会退出,整个程序也不会退出(程序会被无限挂起);

 

    * 对于守护线程,即使线程任务还没有结束,如果主线程退出该线程也会退出

   * 守护线程作用:如果一个服务无法用一种容易的方法来中断线程,或者希望线程工作到一半时中止而不损失或破坏数据,对于这些服务,使用守护线程就很有用。要标志一个线程为守护线程,需要调用其setDaemon()放法并提供参数True。

   ---默认情况下线程不是守护线程。

   * 实例如下:

  #coding=utf8
  import threading
  import time
  import logging

  logging.basicConfig(level=logging.DEBUG, format='(%(threadName)-10s %(message)s', )

  def daemon():
      logging.debug('Starting')
      time.sleep(2)
      logging.debug('Exiting')
    #这个函数执行线程,设置为守护线程以后,这里就不会再输出Exiting。因为在守护线程从其2秒的睡眠时间唤醒之前,所有非守护线程(包括主线程)已经退出。
    #主线程退出后,守护线程也会退出,所以上边不会输出Exiting。
    #(对于守护线程,即使线程任务还没有结束,如果主线程退出该线程也会退出;)

  d=threading.Thread(name='daemon', target=daemon)
  d.setDaemon(True)  #如果这里注释掉,程序执行时,就会停顿2秒,输出Exiting。(为什么?因为对于普通线程,如果线程的任务没有结束,主线程不会退出,整个程序也不会退出;)


  def non_daemon():
      logging.debug('Starting')
      logging.debug('Exiting')
  t=threading.Thread(name='non-daemon', target=non_daemon)

  d.start()
  t.start()
  * 要等待一个守护线程完成工作,需要使用join()方法。(join的作用:即使主线程退出,守护线程的任务没有结束,守护线程也不退出。)

  1),在上边代码的最后加上如下代码

  d.join()

  t.join()

  使用join()等待守护线程退出,这意味着它就会输出"Exiting"消息。加了join以后,守护线程等于变成了普通线程了。

  (daemon     Starting
  (non-daemon Starting
  (non-daemon Exiting
  (daemon     Exiting

  2),默认情况下,join()会无限阻塞。还可以传入一个浮点数值,表示等待线程变为不活动所需的时间(秒数)。即使线程在这个时间段内未完成,join()也会返回。

   d.join(1)

   print 'd.isAlive()',d.isAlive()  //用isAlive()方法判断线程是否活动,true表示活动--存活,false表示不活动--中断,不存活。

   t.join()

   time.sleep(3)  //如果不加下边三行代码,就不会输出(daemon     )Exiting,守护线程会随主线程的退出而退出
   print d.isAlive()  
   print t.isAlive()

   由于传入的超时时间小于守护线程睡眠的时间,所以join()返回之后这个线程扔'存活'。在上面代码中,守护线程设置睡眠2秒(time.sleep(2)),上边,我们设置time.sleep(3),延长主线程退出时间,所以下边(daemon     )Exiting依然会输出。输出所有后,两个线程的状态都是False(中断)。

  

    (daemon     ) Exiting

    False

    False

 

  

 

 

 

 

posted on 2014-04-17 15:21  学到老死  阅读(459)  评论(0)    收藏  举报