繁体   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