簡體   English   中英

Python卡在多線程程序的單線程中

[英]Python stuck in a single thread of a multi-threaded program

我目前正在編寫一個程序,試圖同步訪客到達的動物園的訪客,汽車,泵和加油站線程,等待可用的汽車,游覽,然后退出,每5次騎行必須加油,並且每次加油3輛汽車時,加油站必須加油。 我的測試是在35位訪客,6輛汽車,5個加油站和2個時間間隔下進行的。程序讀取文本文件,其中包含訪客,汽車,水泵的數量以及訪客登車之間的時間間隔,然后使用數據補課。 我為每個線程創建方法,然后在main中自己創建線程。 我的問題是,在運行第一個線程方法visitor_thread之后,我的程序被卡在6輛車上,這是文本文件指定的數量,並且我無法確定是否還有其他線程在同時運行。 我是多線程和python領域的新手,但我不確定是什么問題。 我已經連續12個小時從事該項目的工作,而在過去的四個小時中,我一直處於這一狀態。 從理論上講,visitor_thread,car_thread和gas_station_thread都應從main並發運行,並且visitor_thread應該在某些訪問者完成騎行之后讓車輛可以再次使用,但是我只是在visitor_thread內無限循環地陷入了六輛滿滿的汽車中。 是什么導致此無限循環,如何確保所有線程都在實際運行?

我的代碼:

from threading import Thread
from threading import Lock
from threading import Event

event = Event()
lock = Lock()
done = Event()
is_done = 0


class Arguments:
def __init__(self, m_visitors, n_cars, k_pumps, t_time, thread_num, _done):
    self.m_visitors = m_visitors
    self.n_cars = n_cars
    self.k_pumps = k_pumps
    self.t_time = t_time
    self.thread_num = thread_num
    self.done = _done


class Car:
def __init__(self, control, rides, time, in_service, int_cus, in_queue):
    self.control = control
    self.rides = rides
    self.time = time
    self.in_service = in_service
    self.int_cus = int_cus
    self.in_queue = in_queue


class Pump:
def __init__(self, control, in_use, car_num, time):
    self.control = control
    self.in_use = in_use
    self.car_num = car_num
    self.time = time


class PumpQueue:
def __init__(self, pQueue, MAXsize, front, back, size):
    self.q = Lock()
    self.pQueue = pQueue
    self.MAXsize = MAXsize
    self.front = front
    self.back = back
    self.size = size


def visitor_thread(_visitor):
global is_done
visitor = _visitor

v = visitor.m_visitors
c = visitor.n_cars
p = visitor.k_pumps
t = visitor.t_time
id = visitor.thread_num

i = 0
j = 0
while i < v:
    for j in range(0, c):
        lock.acquire()
        if cars[j].in_service is False and cars[j].rides < 5:
            print('\nVisitor %d is currently in car %d' % (i+1, j+1))
            cars[j].in_service = True
            i += 1
            print('\n%d customers waiting for a ride.' % (v - i))
            lock.release()
            break
        lock.release()
lock.acquire()
is_done += 1
lock.release()


def car_thread(_car):
global is_done
carThread = _car
cars_done = 0

v = carThread.m_visitors
c = carThread.n_cars
p = carThread.k_pumps
t = carThread.t_time
id = carThread.thread_num
i = 0

while cars_done == 0:
    cars_in_service = 0
    while i < c:
        lock.acquire()
        if cars[i].in_service is True and cars[i].rides < 5:
            # Car still being used, add more time
            cars[i].time += 1
        if cars[i].time == t:
            cars[i].in_service = False
            cars[i].rides += 1
            cars[i].time = 0
        if cars[i].rides == 5 and cars[i].in_queue is False:
            push(i)
            cars[i].in_queue = True
        if cars[i].in_service is False:
            cars_in_service += 1
        i += 1
        lock.release()
    if cars_in_service == c and is_done >= 1:
        cars_done = 1
lock.acquire()
is_done += 1
lock.release()


def gas_station_thread(_gas_station):
global is_done
gas_station = _gas_station

truck = False
cars_filled = 0

v = gas_station.m_visitors
c = gas_station.n_cars
p = gas_station.k_pumps
t = gas_station.t_time
id = gas_station.thread_num

gas_done = 0
pumps_in_service = 0

j = 0
while gas_done == 0:
    while j < p:
        lock.acquire()
        if pumps[j].in_use is True:
            pumps[j].time += 1
        if pumps[j].time == 3:
            lock.acquire()
            cars[j].in_service = 0
            cars[j].rides = 0
            cars[j].time = 0
            cars[j].in_queue = False
            lock.release()
            pumps[j].time = 0
            pumps[j].in_use = False
            cars_filled += 1
            pumps_in_service -= 1
        if truck is True and pumps[j].in_use is False:
            truck = False
            print('Fuel Truck is currently filling up the gas station.')
        elif pumps[j].in_use is True and pump_line.size > 0:
            pumps_in_service += 1
            pumps[j].in_use = True
            pumps[j].car_num.pop()
            print('Car %d, pump %d' % (pumps[j].car_num + 1, i + 1))
            pumps[j].time = 0
        j += 1
        lock.release()

        if cars_filled > 3:
            print('The Fuel Truck is on its way')
            truck = True
            cars_filled = 0
        if pumps_in_service == 0 and is_done == 2:
            gas_done = True
        lock.acquire()
        is_done += 1
        lock.release()


def pop():
lock.acquire()
fr = pump_line.front
f = pump_line.pQueue[fr]
print("\n%d cars are waiting for pumps" % int(pump_line.size - 1))
if fr < (pump_line.MAXsize - 1):
    pump_line.front += 1
else:
    pump_line.front = 0
lock.release()

return f


def push(_c):
c =_c
lock.acquire()
b = pump_line.back
pump_line.pQueue[b] = c
print("\n%d cars are waiting for pumps" % int(pump_line.size + 1))
if b < (pump_line.MAXsize - 1):
    pump_line.back += 1
else:
    pump_line.back = 0
lock.release()


def isEmpty():
lock.acquire()
if (pump_line.front == pump_line.back):
    boolean = True
else:
    boolean = False
lock.release()

return boolean

if __name__ == "__main__":
arguments = Arguments(0, 0, 0, 0, 0, False)
main = Arguments(0, 0, 0, 0, 0, False)
thread = []
round_number = 0
io_control = 0
input_file = []
number_of_threads = 3
print("Enter the name of the text file to use as input:")
while io_control == 0:
    try:
        filename = input()
        input_file = open(filename)
        io_control = 1
    except IOError:
        print("Specified file does not exist, enter a different text file:")

# parse file into lines, separating by endlines
file_lines = []
num_lines = 0
for line in input_file:
    line = line.replace(",", " ")
    line = line.split()
    num_lines += 1
    if line:
        line = [int(i) for i in line]
        file_lines.append(line)

while main.done is False and round_number < num_lines:
    main.m_visitors = int(file_lines[round_number][0])
    main.n_cars = int(file_lines[round_number][1])
    main.k_pumps = int(file_lines[round_number][2])
    main.t_time = int(file_lines[round_number][3])

    print("\nRound Number: %d" % (round_number + 1))

    if main.n_cars == 0:
        print('No data to read in this round, press enter to continue:')
        input()

    print("Number of Visitors: %d" % main.m_visitors)
    print("Number of Cars: %d" % main.n_cars)
    print("Number of Pumps: %d" % main.k_pumps)
    print("Units of Time: %d" % main.t_time)

    M = main.m_visitors
    N = main.n_cars
    K = main.k_pumps
    T = main.t_time

    thread_info = []
    cars = []
    pumps = []
    for i in range(0, 3):
        temp = Arguments(M, N, K, T, i, False)
        thread_info.append(temp)

    for i in range(0, N):
        temp = Car(0, 0, 0, False, 0, False)
        cars.append(temp)

    for i in range(0, K):
        temp = Pump(0, False, 0, 0)
        pumps.append(temp)

    pump_line = PumpQueue(0, 0, 0, 0, N)

    visitorThread = Thread(target=visitor_thread, args=(thread_info[0],))
    thread.append(visitorThread)

    carsThread = Thread(target=car_thread, args=(thread_info[1],))
    thread.append(carsThread)

    gasThread = Thread(target=gas_station_thread, args=(thread_info[2],))
    thread.append(gasThread)

    visitorThread.start()
    carsThread.start()
    gasThread.start()

    visitorThread.join()
    carsThread.join()
    gasThread.join()

    round_number += 1

我的輸出:

輪數:1訪客人數:35轎車數量:6泵數量:5時間單位:2

訪客1目前在汽車1中

34位顧客在等車。

訪客2目前在車2中

33位顧客在等車。

訪客3當前在汽車3中

32位顧客在等車。

訪客4當前在汽車4中

31位顧客在等車。

訪客5當前在車5中

30位顧客在等車。

訪客6目前在汽車6中

29位顧客在等車。

我認為這里存在索引問題:

 if cars[j].in_service is False and cars[i].rides < 5:

應該

if cars[j].in_service is False and cars[j].rides < 5:

汽車指數不是j

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM