2014-10-12 75 views
0

我目前的困境是我試圖做一個阻塞的web服務腳本非阻塞,以允許在任何時候發生多個下載,但目前它會掛起並等待首先下載完成後再開始第二個。在你投票決定之前,因爲答案是可惡的,請知道這是我第一次使用python腳本,我是自學教程。爲什麼我的python線程互相阻塞

在下面的例子中我只發佈一個「ConnectionProcesser」因爲它們都含有相同的代碼 如果你需要更多的代碼,請只問

腳本有3個dependinces

import socket # Networking support 
import signal # Signal support (server shutdown on signal receive) 
import threading #to make the thing run more than one at a time 

請注意該腳本已被編輯,並且相當一部分代碼已丟失,但我認爲它與該問題無關。

def ConnectionProcessorC(self): 
    connC, AddressC = self.socket.accept() 
    print("C Got connection from:", AddressC) 
    DataRecivedC = connC.recv(1024) #receive data from client 
    DataRecivedC = bytes.decode(DataRecivedC) #decode it to string 
    print(DataRecivedC) 
    RequestMethod = DataRecivedC.split(' ')[0] 
    print ("C Method: ", RequestMethod) 
    if (RequestMethod == 'GET') | (RequestMethod == 'HEAD'): 
     Response_Headers = 'HTTP/1.1 200 OK\n' 
     # Current_Date = time.strftime("%a, %d %b %Y %H:%M:%S", time.localtime()) 
     # Response_Headers += 'Date: ' + current_date +'\n' 
     Response_Headers += 'Server: Moes-Python-Server\n' 
     Response_Headers += 'Connection: close\n\n' # signal that the conection wil be closed after complting the request 
     Server_Response = Response_Headers.encode() # return headers for GET and HEAD 
     file_handler = open('/usr/share/nginx/html/100mb.dump','rb') 
     Response_Content = file_handler.read() # read file content 
     file_handler.close() 
     URL=DataRecivedC.split(' ') 
     URL = URL[1] # get 2nd element 
     #Response_Content="<html><body><p>Charlie TEStin this stuff yehURL:"+URL+"</p></body></html>" 
     Server_Response += Response_Content 

     connC.send(Server_Response) 
     print ("C Closing connection with client") 
    else: 
     print("C Unknown HTTP request method:", RequestMethod) 

    connC.close() 
    return 
def Distrabuteconnections(self): 
    A=0 
    """ Main loop awaiting connections """ 
    while True: 
     print ("Awaiting New connection") 
     self.socket.listen(10) # maximum number of queued connections #changed to 1 from 3 to try and prevent waiting after closing for ther que to clean up 

     if (A==0): 
      ConnectionProcessorA = threading.Thread(target=self.ConnectionProcessorA()) 
      ConnectionProcessorA.start() 
      A=1 
     elif (A==1): 
      ConnectionProcessorB = threading.Thread(target=self.ConnectionProcessorB()) 
      ConnectionProcessorB.start() 
      A=2 
     else: 
      ConnectionProcessorC = threading.Thread(target=self.ConnectionProcessorC()) 
      ConnectionProcessorC.start() 
      A=0 

我認爲這個問題可以通過改變來解決,而真正的事情是循環3次而不是一次。

+0

從線程切換到子進程應該解決它 – 2014-10-12 00:25:05

+0

但爲什麼我需要的子進程是有什麼原因?他們不跑得慢嗎? – door 2014-10-12 00:26:09

+0

子進程可能需要更長的時間才能啓動並且內存佔用量更高,但沒有理由爲什麼它們會變慢。原因將是GIL,這似乎干擾線程。這不在子流程中發生。 – 2014-10-12 00:27:43

回答

0

你應該傳遞一個你想在線程中啓動的方法的引用。相反,您正在調用線程,並將從該方法返回的數據傳遞給threading.Thread()調用。

總之你的代碼應該變成:

 if (A==0): 
     ConnectionProcessorA = threading.Thread(target=self.ConnectionProcessorA) 
     ConnectionProcessorA.start() 
     A=1 
    elif (A==1): 
     ConnectionProcessorB = threading.Thread(target=self.ConnectionProcessorB) 
     ConnectionProcessorB.start() 
     A=2 
    else: 
     ConnectionProcessorC = threading.Thread(target=self.ConnectionProcessorC) 
     ConnectionProcessorC.start() 
     A=0 

self.ConnectionProcessorA等後去掉括號這傳遞給方法的引用的線程,線程模塊調用自身開始。

請注意,建議存儲對您創建的線程的引用,以避免垃圾收集。因此,我建議你的代碼變成:

 if (A==0): 
     self.cpa_thread= threading.Thread(target=self.ConnectionProcessorA) 
     self.cpa_thread.start() 
     A=1 
    elif (A==1): 
     self.cpb_thread= threading.Thread(target=self.ConnectionProcessorB) 
     self.cpb_thread.start() 
     A=2 
    else: 
     self.cpc_thread= threading.Thread(target=self.ConnectionProcessorC) 
     self.cpc_thread.start() 
     A=0 
+0

我試過你的代碼,它所做的一切都是反覆運行ConnectionProcessorA,所以我無法測試它是否有效 – door 2014-10-12 00:46:17

+0

我認爲我需要做的是刪除while while true,並在創建連接時使用線程內部的調用替換它,以便腳本不會像創建線程一樣繼續創建線程 – door 2014-10-12 00:50:01

+0

我會期望所有3個線程仍然運行,但是最好每次建立連接時都生成一個線程。可能你可以在主線程中調用'socket.accept()',並將'connX'和'AddressX'變量傳遞給線程。如果您需要幫助改變程序的架構,最好用一個**最小化的工作示例**發佈一個新問題,以便您可以真正運行一些代碼來模擬您正在做的事情。 – 2014-10-12 03:48:48

相關問題