进程和线程

  • 线程基本使用方法
    • 直接使用Thread类,传入要运行的方法和参数
      #直接使用Thread,传入要运行的方法和参数
      def action(arg):
          for k in range(10):
              if (arg == 1):  #第一个线程执行三秒的休眠
                  time.sleep(3)
              else:
                  time.sleep(1)
              print('the arg is:%s' % arg, '\t', k, datetime.datetime.now())
      for i in range(4):
          print("start", datetime.datetime.now())
          t =threading.Thread(target=action,args=(i,))
          t.start()
      print('main thread end!') 
      
      • 在上述线程操作函数的定义中,第一个线程每次休眠三秒钟,其他线程每次休眠1秒钟,所以在正常的情况下,执行结果如下:
        进程和线程
      • 三个线程的开启时间均为第10秒,然后在11和12秒,除第1个线程的其他线程均有执行,第1个线程在13秒才有执行。
    • 继承Thread类,重载run()方法
      #方法二:从Thread继承,并重写run()
      class MyThread(threading.Thread):
          	def __init__(self,arg):
              super(MyThread, self).__init__()#注意:一定要显式的调用父类的初始化函数。
              self.arg=arg
      def run(self):   #定义每个线程要运行的函数
              for k in range(10):
                  if(self.arg == 1):
                      time.sleep(3)
                  else:
                      time.sleep(1)
                  print('the arg is:%s' % self.arg,'\t',k,datetime.datetime.now())
      thread_list=[]
      for i in range(4):
          print("start",datetime.datetime.now())
          t =MyThread(i)
          thread_list.append(t)
          #t.setDaemon(True)  #设置子线程是否为守护线程(随主线程结束而结束)
          t.start()
      print('main thread end!')
      
  • 继承的类不要忘了执行super语句,继承父类的初始化函数,然后重载run()方法,在里边写线程的操作函数。
    - 函数执行结果如上图
  • 守护线程设置和join()方法的使用
    • 当一个进程启动后,会默认产生一个主线程,而主线程创建的线程称为子线程

    • python中,线程有一个setDaemon的函数,该函数用户设置子线程是否为守护线程,守护线程是指子线程随主线程的结束而结束,默认为False。当设置为True时

       t =MyThread(i)
       thread_list.append(t)
       t.setDaemon(True)  #设置子线程是否为守护线程(随主线程结束而结束)
       t.start()
      
    • 执行结果如下:

      • 主线程一结束,子线程来不及执行就停止
        进程和线程
    • join函数

      • join函数实现线程的同步,即主线程任务结束之后,会进入阻塞状态,一直等待其他的子线程执行结束后,主线程再终止。
        for t in thread_list:
            t.join()
            t.join()
        
      • 执行结果如上图
        进程和线程
      • 线程锁的概念
        注意线程锁的意思并不是要给资源加锁,而是要用锁去锁住资源,一般可以先定义一个锁,需要独占某一资源时,可以使用锁锁住该资源
        锁的操作包括如下
        #创建锁
        mutex = threading.Lock()
        #锁定
        mutex.acquire([timeout])
        #释放
        mutex.release()
        注:timeout是锁定的最大时间
        
        • 代码实现
          #线程锁的实现
          	counter = 0  #定义一个全局变量,所有线程都可以操作
          	counter_lock = threading.Lock()  #定义一个锁
          	
          	class MyThread(threading.Thread):
          	    def __init__(self,arg):
          	        super(MyThread, self).__init__()#注意:一定要显式的调用父类的初始化函数。
          	        self.arg=arg
          	
          	    def run(self):   #定义每个线程要运行的函数
          	        global counter,counter_lock
          	        for k in range(10):
          	            '''
          	            if(self.arg == 1):
          	                time.sleep(3)
          	            else:
          	                time.sleep(1)
          	            '''
          	            time.sleep(1)
          	            if counter_lock.acquire():
          	                counter += 1
          	                print('the arg is:%s' % self.arg,'\t','counter is  :%s' % counter,'\t',k,datetime.datetime.now())
          	                counter_lock.release()
          	thread_list=[]
          	for i in range(4):
          	    print("start",datetime.datetime.now())
          	    t =MyThread(i)
          	    thread_list.append(t)
          	    t.start()
          	print('main thread end!')
          
        • 上述代码中,每个线程休眠一秒然后执行,在修改counter变量时,加锁,防止其他线程访问,结果如下:
          进程和线程
    • 参考