线程在java中使用相同的变量

时间:2016-03-28 11:18:57

标签: java multithreading

我正在处理线程并遇到问题,因为我的线程使用的是基于另一个类的其他线程创建的相同变量。 问题出在这个代码上:

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);

但是线程在同一时间寻找相同的值,所以我所能做的就是随机时间休眠,然后他们不能在同一时间检查真值,但是使用随机我仍然可以得到两个相同的值,所以飞机有时会飞到同一个目标。 我认为有更好的方法,但不知道。请帮忙。

2 个答案:

答案 0 :(得分:0)

我看到的方式是所有线程同时访问同一个请求列表,而不是循环遍历

CODE

让您的列表像堆栈一样,逐个弹出请求。这样每个pop都会给你的线程一个单独的请求。

答案 1 :(得分:0)

我稍微清理了你的代码。它并不完全清楚为什么你首先使用线程。您可以在主线程中循环遍历列表并创建平面对象。例如,那些可以存储在列表中。我假设您可能想使用线程来模拟飞行的飞机?如果是这种情况并且在while(inBase)之后run方法没有完成,那么你可能想要使用一个锁对象来确保一次只有一个线程可以修改你的世界:

//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 auch eine Insel - ReentrantLock