简体   繁体   中英

Threads using the same variable in java

I'm working with threads and have a problem, because my threads are using the same variables created by other thread based on another class. The problem is with this code:

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

The result is:

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

As you see Airplanes are flying to the same City and that's wrong. Don't know what should I do to prevent this situation, because I have already done condition

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

And then I change this value to false

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

But thread are looking for the same value in the same time, so all I can do is sleep each for random time then they won't check true value in the same time, but using random I can still get two the same values so Airplanes sometimes will fly to the same target. I think there is a better way to do it but have no idea. Please help.

The way i see is that all of your threads get access to the same request list at the same time so, instead of looping through

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

have your list behave like a stack and pop the requests out one by one. This way each pop will give your thread a separate request.

I cleaned up your code a little. Its not entirely clear why you use threads in the first place. You could very well just loop through your list in your main thread and create plane objects. Those could be stored in a list for example. I assume you might want to use the threads to simulate the planes flying? If that is the case and the run method is not finished after the while(inBase) then you might want to use a lock object to make sure only one thread at a time can modify your world:

//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.
}

Some more infos about ReentrantLock: Java ist auch eine Insel - ReentrantLock

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM