Python多線程循環


背景:Python腳本:讀取文件中每行,放入列表中;循環讀取列表中的每個元素,並做處理操作。
核心:多線程處理單個for循環函數調用

模塊:threading

第一部分:
 
:多線程腳本 (該腳本只有兩個線程,t1循環次數<t2)
 
#!/usr/bin/env python
#-*- coding: utf8 -*-

import sys
import time
import string
import threading
import datetime
fileinfo = sys.argv[1]

# 讀取文件內容放入列表
host_list = []
port_list = []
 
# 定義函數:讀取文件內容放入列表中
def CreateList():
    f = file(fileinfo,'r')
    for line in f.readlines():
        host_list.append(line.split(' ')[0])
        port_list.append(line.split(' ')[1])
    return host_list
    return port_list
    f.close()
 
# 單線程 循環函數,注釋掉了
#def CreateInfo():    
#    for i in range(0,len(host_list)):     # 單線程:直接循環列表
#        time.sleep(1)
#        TimeMark = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
#        print "The Server's HostName is %-15s and Port is %-4d !!! [%s]" % (host_list[i],int(port_list[i]),TimeMark)
#    
 
#  定義多線程循環調用函數 
def MainRange(start,stop):     #提供列表index起始位置參數
    for i in range(start,stop):
        time.sleep(1)
        TimeMark = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        print "The Server's HostName is %-15s and Port is %-4d !!! [%s]" % (host_list[i],int(port_list[i]),TimeMark)
 
# 執行函數,生成列表
CreateList()
# 列表分割成:兩部分 mid為列表的index中間位置
mid = int(len(host_list)/2)
 
# 多線程部分
threads = []
t1 = threading.Thread(target=MainRange,args=(0,mid))
threads.append(t1)
t2 = threading.Thread(target=MainRange,args=(mid,len(host_list)))
threads.append(t2)

for t in threads: t.setDaemon(True) t.start() t.join() print "ok"  

 

以上是腳本內容!!!

----------------------------------------------------------------------

:讀取文件的內容
文件內容:
[root@monitor2 logdb]# cat hostinfo.txt
192.168.10.11 1011
192.168.10.12 1012
192.168.10.13 1013
192.168.10.14 1014
192.168.10.15 1015
192.168.10.16 1016
192.168.10.17 1017
192.168.10.18 1018
192.168.10.19 1019
192.168.10.20 1020
192.168.10.21 1021
192.168.10.22 1022
192.168.10.23 1023
192.168.10.24 1024
192.168.10.25 1025
 
:輸出結果:
單線程 : 執行腳本:輸出結果:
[root@monitor2 logdb]# ./Threadfor.py hostinfo.txt
The Server's HostName is 192.168.10.10   and Port is 1010 !!! [2017-01-10 14:25: 14]
The Server's HostName is 192.168.10.11   and Port is 1011 !!! [2017-01-10 14:25: 15]
The Server's HostName is 192.168.10.12   and Port is 1012 !!! [2017-01-10 14:25: 16]
     .
     .
     .
The Server's HostName is 192.168.10.25   and Port is 1025 !!! [2017-01-10 14:25: 29]
 
多線程:執行腳本:輸出 結果

[root@monitor2 logdb]# ./Threadfor.py hostinfo.txt
The Server's HostName is 192.168.10.11 and Port is 1011 !!! [2017-01-10 14:51:51]
The Server's HostName is 192.168.10.18 and Port is 1018 !!! [2017-01-10 14:51:51]
The Server's HostName is 192.168.10.12 and Port is 1012 !!! [2017-01-10 14:51:52]
The Server's HostName is 192.168.10.19 and Port is 1019 !!! [2017-01-10 14:51:52]
The Server's HostName is 192.168.10.13 and Port is 1013 !!! [2017-01-10 14:51:53]
The Server's HostName is 192.168.10.20 and Port is 1020 !!! [2017-01-10 14:51:53]
The Server's HostName is 192.168.10.14 and Port is 1014 !!! [2017-01-10 14:51:54]
The Server's HostName is 192.168.10.21 and Port is 1021 !!! [2017-01-10 14:51:54]
The Server's HostName is 192.168.10.15 and Port is 1015 !!! [2017-01-10 14:51:55]
The Server's HostName is 192.168.10.22 and Port is 1022 !!! [2017-01-10 14:51:55]
The Server's HostName is 192.168.10.16 and Port is 1016 !!! [2017-01-10 14:51:56]
The Server's HostName is 192.168.10.23 and Port is 1023 !!! [2017-01-10 14:51:56]
The Server's HostName is 192.168.10.17 and Port is 1017 !!! [2017-01-10 14:51:57]
The Server's HostName is 192.168.10.24 and Port is 1024 !!! [2017-01-10 14:51:57]
The Server's HostName is 192.168.10.25 and Port is 1025 !!! [2017-01-10 14:51:58]

==================================以上部分完結===正確=========

=====經過調試出現新的問題======================================

 

第二部分:延伸問題

總結:以上運行結果沒有問題!!!(但是調整參數:start,stop之后有問題:MainRange(start,stop))

首先說明下兩個概念問題:

  join():

    1.方法的位置是在for循環外的,也就是說必須等待for循環里的兩個進程都結束后,才去執行主進程(主進程指:本腳本中的print “OK”)。

    2.可以理解成:t.join() 的t線程執行完之后,再繼續執行后面的!!!(本腳本中的t.join(),是指t2線程)

    可參考:

      for i in range(0,4):

        pass

      print i

      結果輸出:3. 也就是for循環的最后一個i. 放在本腳本里,就是for循環的最后一個線程t2。然后t2完成之后,就是:print “OK”

        

  setDaemon(True):

    1.將線程聲明為守護線程,必須在start() 方法調用之前設置,如果不設置為守護線程程序會被無限掛起。

    2.換句話說:開啟,子線程不會掛起,主線程執行了,子線程及時沒執行完也會中斷:比如本腳本里如果:t1>t2

 ===========解析=============================================================

重新編寫輸出文件內容:

[root@monitor2 logdb]# cat hostinfo.txt
192.168.10.00 0
192.168.10.01 1
192.168.10.02 2
192.168.10.03 3
192.168.10.04 4
192.168.10.05 5
192.168.10.06 6
192.168.10.07 7
192.168.10.08 8
192.168.10.09 9
192.168.10.10 10
192.168.10.11 11
192.168.10.12 12
192.168.10.13 13
192.168.10.14 14

原文腳本中:

for t in threads: t.setDaemon(True) t.start() t.join() print "ok" 

分類解析:

基於原文腳本:

1. 以上基於線程執行次數:t1 <= t2  運行結果:正確

[root@monitor2 logdb]# ./Threadfor.py hostinfo.txt
The Server's HostName is 192.168.10.00   and Port is 00 !!! [2017-01-10 19:08:44],
The Server's HostName is 192.168.10.07   and Port is 07 !!! [2017-01-10 19:08:44],
The Server's HostName is 192.168.10.01   and Port is 01 !!! [2017-01-10 19:08:45],
The Server's HostName is 192.168.10.08   and Port is 08 !!! [2017-01-10 19:08:45],
The Server's HostName is 192.168.10.02   and Port is 02 !!! [2017-01-10 19:08:46],
The Server's HostName is 192.168.10.09   and Port is 09 !!! [2017-01-10 19:08:46],
The Server's HostName is 192.168.10.03   and Port is 03 !!! [2017-01-10 19:08:47],
The Server's HostName is 192.168.10.10   and Port is 10 !!! [2017-01-10 19:08:47],
The Server's HostName is 192.168.10.04   and Port is 04 !!! [2017-01-10 19:08:48],
The Server's HostName is 192.168.10.11   and Port is 11 !!! [2017-01-10 19:08:48],
The Server's HostName is 192.168.10.05   and Port is 05 !!! [2017-01-10 19:08:49],
The Server's HostName is 192.168.10.12   and Port is 12 !!! [2017-01-10 19:08:49],
The Server's HostName is 192.168.10.06   and Port is 06 !!! [2017-01-10 19:08:50],
The Server's HostName is 192.168.10.13   and Port is 13 !!! [2017-01-10 19:08:50],
The Server's HostName is 192.168.10.14   and Port is 14 !!! [2017-01-10 19:08:51],
ok

  解析:開啟setDaemon(True),t1,t2同時依次執行,[t1,t2],[t1,t2],[t1,t2],[t1,t2],[t1,t2] . . . . . .[t1,t2], 下次循環t1結束,t2再執行一次,[,t2],再下次,t2結束。t.join()==t2.join() 完成任務,繼續執行主進程print “ok”

 

2.基於腳本中線程次數t1>t2,運行結果:錯誤

[root@monitor2 logdb]# ./Threadfor.py hostinfo.txt
t1: (0~13)
t2: (7~15)
The Server's HostName is 192.168.10.00   and Port is 00 !!! [2017-01-10 19:18:58],
The Server's HostName is 192.168.10.07   and Port is 07 !!! [2017-01-10 19:18:58],
The Server's HostName is 192.168.10.01   and Port is 01 !!! [2017-01-10 19:18:59],
The Server's HostName is 192.168.10.08   and Port is 08 !!! [2017-01-10 19:18:59],
The Server's HostName is 192.168.10.02   and Port is 02 !!! [2017-01-10 19:19:00],
The Server's HostName is 192.168.10.09   and Port is 09 !!! [2017-01-10 19:19:00],
The Server's HostName is 192.168.10.03   and Port is 03 !!! [2017-01-10 19:19:01],
The Server's HostName is 192.168.10.10   and Port is 10 !!! [2017-01-10 19:19:01],
The Server's HostName is 192.168.10.04   and Port is 04 !!! [2017-01-10 19:19:02],
The Server's HostName is 192.168.10.11   and Port is 11 !!! [2017-01-10 19:19:02],
The Server's HostName is 192.168.10.12   and Port is 12 !!! [2017-01-10 19:19:03],
The Server's HostName is 192.168.10.05   and Port is 05 !!! [2017-01-10 19:19:03],
The Server's HostName is 192.168.10.13   and Port is 13 !!! [2017-01-10 19:19:04],
The Server's HostName is 192.168.10.06   and Port is 06 !!! [2017-01-10 19:19:04],
The Server's HostName is 192.168.10.07   and Port is 07 !!! [2017-01-10 19:19:05],
The Server's HostName is 192.168.10.14   and Port is 14 !!! [2017-01-10 19:19:05],
ok

   解析:t1,t2同時依次執行,t1>t2,當t2執行最后一次時,t.join()===t2.join(),t.join()完成任務,執行主程序print "ok",由於:開啟setDaemon(True),t1,t2均不會被掛起,主程序結束,子程序即使沒有執行完,也結束。如上述結果。

  t2執行8次結束,t1也執行8次循環結束。

 

開啟:t.setDaemon(True):不會掛起,順序執行

1.腳本如下:

for t in threads:

  t.setDaemon(True)

  t.start()

  t.join()   #在for循環里面

print "ok"

[root@monitor2 logdb]# ./Threadfor.py hostinfo.txt
t1: (0~13)
t2: (7~15)
The Server's HostName is 192.168.10.00   and Port is 00 !!! [2017-01-10 19:30:56]
The Server's HostName is 192.168.10.01   and Port is 01 !!! [2017-01-10 19:30:57]
The Server's HostName is 192.168.10.02   and Port is 02 !!! [2017-01-10 19:30:58]
The Server's HostName is 192.168.10.03   and Port is 03 !!! [2017-01-10 19:30:59]
The Server's HostName is 192.168.10.04   and Port is 04 !!! [2017-01-10 19:31:00]
The Server's HostName is 192.168.10.05   and Port is 05 !!! [2017-01-10 19:31:01]
The Server's HostName is 192.168.10.06   and Port is 06 !!! [2017-01-10 19:31:02]
The Server's HostName is 192.168.10.07   and Port is 07 !!! [2017-01-10 19:31:03]
The Server's HostName is 192.168.10.08   and Port is 08 !!! [2017-01-10 19:31:04]
The Server's HostName is 192.168.10.09   and Port is 09 !!! [2017-01-10 19:31:05]
The Server's HostName is 192.168.10.10   and Port is 10 !!! [2017-01-10 19:31:06]
The Server's HostName is 192.168.10.11   and Port is 11 !!! [2017-01-10 19:31:07]
The Server's HostName is 192.168.10.12   and Port is 12 !!! [2017-01-10 19:31:08]
The Server's HostName is 192.168.10.07   and Port is 07 !!! [2017-01-10 19:31:09]
The Server's HostName is 192.168.10.08   and Port is 08 !!! [2017-01-10 19:31:10]
The Server's HostName is 192.168.10.09   and Port is 09 !!! [2017-01-10 19:31:11]
The Server's HostName is 192.168.10.10   and Port is 10 !!! [2017-01-10 19:31:12]
The Server's HostName is 192.168.10.11   and Port is 11 !!! [2017-01-10 19:31:13]
The Server's HostName is 192.168.10.12   and Port is 12 !!! [2017-01-10 19:31:14]
The Server's HostName is 192.168.10.13   and Port is 13 !!! [2017-01-10 19:31:15]
The Server's HostName is 192.168.10.14   and Port is 14 !!! [2017-01-10 19:31:16]
ok

  :解析:t.join()在for循環里面,t1.join()等待t1執行13次循環完畢;然后才執行t2,t2.join()等待t2循環執行8次;然后執行主線程print"ok"

   :如上述結果:t1先執行完,再執行t2

  :t1,t2大小無所謂,多線程沒有效果

關閉:t.setDaemon(True) :線程會掛起

1.腳本如下:

for t in threads:

#  t.setDaemon(True)

  t.start()

  t.join()   #在for循環里面

print "ok"

[root@monitor2 logdb]# ./Threadfor.py hostinfo.txt
t1: (0~13)
t2: (7~15)
The Server's HostName is 192.168.10.00   and Port is 00 !!! [2017-01-10 19:37:11]
The Server's HostName is 192.168.10.01   and Port is 01 !!! [2017-01-10 19:37:12]
The Server's HostName is 192.168.10.02   and Port is 02 !!! [2017-01-10 19:37:13]
The Server's HostName is 192.168.10.03   and Port is 03 !!! [2017-01-10 19:37:14]
The Server's HostName is 192.168.10.04   and Port is 04 !!! [2017-01-10 19:37:15]
The Server's HostName is 192.168.10.05   and Port is 05 !!! [2017-01-10 19:37:16]
The Server's HostName is 192.168.10.06   and Port is 06 !!! [2017-01-10 19:37:17]
The Server's HostName is 192.168.10.07   and Port is 07 !!! [2017-01-10 19:37:18]
The Server's HostName is 192.168.10.08   and Port is 08 !!! [2017-01-10 19:37:19]
The Server's HostName is 192.168.10.09   and Port is 09 !!! [2017-01-10 19:37:20]
The Server's HostName is 192.168.10.10   and Port is 10 !!! [2017-01-10 19:37:21]
The Server's HostName is 192.168.10.11   and Port is 11 !!! [2017-01-10 19:37:22]
The Server's HostName is 192.168.10.12   and Port is 12 !!! [2017-01-10 19:37:23]
The Server's HostName is 192.168.10.07   and Port is 07 !!! [2017-01-10 19:37:24]
The Server's HostName is 192.168.10.08   and Port is 08 !!! [2017-01-10 19:37:25]
The Server's HostName is 192.168.10.09   and Port is 09 !!! [2017-01-10 19:37:26]
The Server's HostName is 192.168.10.10   and Port is 10 !!! [2017-01-10 19:37:27]
The Server's HostName is 192.168.10.11   and Port is 11 !!! [2017-01-10 19:37:28]
The Server's HostName is 192.168.10.12   and Port is 12 !!! [2017-01-10 19:37:29]
The Server's HostName is 192.168.10.13   and Port is 13 !!! [2017-01-10 19:37:30]
The Server's HostName is 192.168.10.14   and Port is 14 !!! [2017-01-10 19:37:31]
ok

  解析:由於t.join()在循環里面,所以:t1線程執行完,才執行t2.是順序執行的

  t1,t2大小無所謂,多線程沒有效果

 

 

2.腳本如下:

 

for t in threads:

 

#  t.setDaemon(True)

 

  t.start()

t.join()   #在for循環外面

 

print "ok"

 

[root@monitor2 logdb]# ./Threadfor.py hostinfo.txt
t1: (0~13)
t2: (7~15)
The Server's HostName is 192.168.10.00   and Port is 00 !!! [2017-01-10 19:40:31]
The Server's HostName is 192.168.10.07   and Port is 07 !!! [2017-01-10 19:40:31]
The Server's HostName is 192.168.10.01   and Port is 01 !!! [2017-01-10 19:40:32]
The Server's HostName is 192.168.10.08   and Port is 08 !!! [2017-01-10 19:40:32]
The Server's HostName is 192.168.10.02   and Port is 02 !!! [2017-01-10 19:40:33]
The Server's HostName is 192.168.10.09   and Port is 09 !!! [2017-01-10 19:40:33]
The Server's HostName is 192.168.10.03   and Port is 03 !!! [2017-01-10 19:40:34]
The Server's HostName is 192.168.10.10   and Port is 10 !!! [2017-01-10 19:40:34]
The Server's HostName is 192.168.10.04   and Port is 04 !!! [2017-01-10 19:40:35]
The Server's HostName is 192.168.10.11   and Port is 11 !!! [2017-01-10 19:40:35]
The Server's HostName is 192.168.10.05   and Port is 05 !!! [2017-01-10 19:40:36]
The Server's HostName is 192.168.10.12   and Port is 12 !!! [2017-01-10 19:40:36]
The Server's HostName is 192.168.10.06   and Port is 06 !!! [2017-01-10 19:40:37]
The Server's HostName is 192.168.10.13   and Port is 13 !!! [2017-01-10 19:40:37]
The Server's HostName is 192.168.10.07   and Port is 07 !!! [2017-01-10 19:40:38]
The Server's HostName is 192.168.10.14   and Port is 14 !!! [2017-01-10 19:40:38]
ok
The Server's HostName is 192.168.10.08   and Port is 08 !!! [2017-01-10 19:40:39]
The Server's HostName is 192.168.10.09   and Port is 09 !!! [2017-01-10 19:40:40]
The Server's HostName is 192.168.10.10   and Port is 10 !!! [2017-01-10 19:40:41]
The Server's HostName is 192.168.10.11   and Port is 11 !!! [2017-01-10 19:40:42]
The Server's HostName is 192.168.10.12   and Port is 12 !!! [2017-01-10 19:40:43]

  解析:t.join()在循環外面t.join()==t2.join(), 

  過程:t1>t2. 開始:同時執行。當t2執行8次循環完畢,t1也執行了8次。此時t2完畢,t.join()生效,會執行主進程print "ok". 主進程完畢。

    由於,關閉:t.setDaemon(True),未執行完畢的t1先前被掛起,接下來會繼續,直到結束。如上述結果

  t1<t2 就不會出現這種情況了。多線程是有效的。但是主線程的輸出位置,錯誤!!


 =============解決方法================================

解決方式:

1.只有兩個線程時

修改原腳本:臨時解決t1>t2

for t in threads:

  t.setDaemon(True)

    t.start()  

threads[0].join()   #指定t1,結束

print "ok"

  解析:通過threads[0] 指定t1.join() ,等t1完成了,才執行主程序

2.多個線程時 也適用

for t in threads:

  t.start()

for t in threads:

  t.join()

print "ok"

  解析:多個線程都等待,等所有都完成之后。才執行主線程print "ok"

3.事例:3個線程

[root@monitor2 logdb]# ./Threadfor.py hostinfo.txt
t1: (0~4)  循環4次
t2: (4~11) 循環7次

t3: (11~15) 循環4次
The Server's HostName is 192.168.10.00   and Port is 00 !!! [2017-01-10 20:07:31]
The Server's HostName is 192.168.10.04   and Port is 04 !!! [2017-01-10 20:07:31]
The Server's HostName is 192.168.10.11   and Port is 11 !!! [2017-01-10 20:07:31]   1次
The Server's HostName is 192.168.10.01   and Port is 01 !!! [2017-01-10 20:07:32]
The Server's HostName is 192.168.10.05   and Port is 05 !!! [2017-01-10 20:07:32]
The Server's HostName is 192.168.10.12   and Port is 12 !!! [2017-01-10 20:07:32]  2次
The Server's HostName is 192.168.10.02   and Port is 02 !!! [2017-01-10 20:07:33]
The Server's HostName is 192.168.10.06   and Port is 06 !!! [2017-01-10 20:07:33]
The Server's HostName is 192.168.10.13   and Port is 13 !!! [2017-01-10 20:07:33]  3次
The Server's HostName is 192.168.10.03   and Port is 03 !!! [2017-01-10 20:07:34]
The Server's HostName is 192.168.10.07   and Port is 07 !!! [2017-01-10 20:07:34]
The Server's HostName is 192.168.10.14   and Port is 14 !!! [2017-01-10 20:07:34]  4次
The Server's HostName is 192.168.10.08   and Port is 08 !!! [2017-01-10 20:07:35]  5次
The Server's HostName is 192.168.10.09   and Port is 09 !!! [2017-01-10 20:07:36]  6次
The Server's HostName is 192.168.10.10   and Port is 10 !!! [2017-01-10 20:07:37]  7次
ok

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM