簡體   English   中英

在Java中使用相同變量的線程

[英]Threads using the same variable in java

我正在使用線程並遇到問題,因為我的線程使用的是基於其他類的其他線程創建的相同變量。 問題在於此代碼:

public void run() {
    int cityID = 0;
    int requestID = 0;
    boolean inBase = true;
    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    while (inBase == true) {
        for (cityID = 0; cityID < world.getCities().size(); cityID++) {
            if ((!world.getCities().get(cityID).getRequestsList().isEmpty()) && (inBase == true)) {
                for (requestID = 0; requestID < world.getCities().get(cityID).getRequestsList()
                        .size(); requestID++) {
                    if (world.getCities().get(cityID).getRequestsList().get(requestID).isRequest() == true) {
                        world.getCities().get(cityID).getRequestsList().get(requestID).setRequest(false);
                        System.out.println(Thread.currentThread().getName() + " is flying to "
                                + world.getCities().get(cityID).getName());
                        inBase = false;
                        break;
                    }
                }
            }
        }
    }
}

結果是:

City 859|342 is sending request for airplane. . .
City 328|669 is sending request for airplane. . .
City 718|287 is sending request for airplane. . .
Airplane kS-2 is flying to City 859|342
Airplane kS-1 is flying to City 859|342

如您所見,飛機正在飛往同一座城市,這是錯誤的。 不知道該怎么辦才能防止這種情況,因為我已經做好了條件

if world.getCities().get(cityID).getRequestsList().get(requestID).isRequest() == true)

然后我將此值更改為false

world.getCities().get(cityID).getRequestsList().get(requestID).setRequest(false);

但是線程在同一時間尋找相同的值,所以我所能做的就是隨機睡眠每個時間,然后他們將不會在同一時間檢查真實值,但是使用隨機值我仍然可以獲得兩個相同的值,所以飛機有時會飛向同一目標。 我認為有更好的方法可以做到,但一無所知。 請幫忙。

我看到的方式是,所有線程都可以同時訪問同一請求列表,而不是循環遍歷

world.getCities().get(cityID).getRequestsList()

讓您的列表表現得像一個堆棧,並一一彈出請求。 這樣,每次彈出都會給您的線程一個單獨的請求。

我整理了一下您的代碼。 尚不清楚為什么首先要使用線程。 您可以在主線程中循環遍歷列表並創建平面對象。 例如,這些可以存儲在列表中。 我假設您可能想使用線程來模擬飛行的飛機? 如果是這種情況,並且運行方法在while(inBase)之后仍未完成,那么您可能希望使用鎖對象來確保一次僅一個線程可以修改您的世界:

//Define a lock object somewhere. Each thread must have access to this somehow.
private final Lock lock = new ReentrantLock();

public void run() {
    boolean inBase = true;
    //This thread is about to use and modify the world.
    //Wait for other threads to finish and occuppy the world by locking.
    lock.lock();
    while (inBase) {
        for (int cityID = 0; cityID < world.getCities().size() && inBase; cityID++) {
            City city = world.getCities().get(cityID);
            if (!city.getRequestsList().isEmpty()) {
                for (int requestID = 0; requestID < city.getRequestsList().size(); requestID++) {
                    Request request = city.getRequestsList().get(requestID);
                    if (request.isRequest()) {
                        request.setRequest(false);
                        System.out.println(Thread.currentThread().getName() + " is flying to " + city.getName());
                        inBase = false;
                        break;
                    }
                }
            }
        }
    }
    //This thread is finished with modifying the world.
    //Release the lock so other threads can use it.
    lock.unlock();
    //Do stuff that planes do while flying.
}

有關ReentrantLock的更多信息: Java ist eine Insel-ReentrantLock

暫無
暫無

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

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