Jordfoz16
Jordfoz16

Reputation: 27

How to pass variables to different Threads in Java

I'm making a program that gets live price information from an API. I then want to display the price information on a JavaFX chart that live updates. When I try to pass the information to the JavaFX Thread it doesn't always pass over correctly and the JavaFX thread doesn't get the price information.

The API call is done on a separate thread and when it has the information it then calls the updateScene method. This is where I get an issue, the API Thread has all the information I try and set the variable for the JavaFX thread to use and it has none of the information.


private CandleStickFeed candleStickFeed;

public void updateScene(CandleStickFeed candleStickFeed){

    this.candleStickFeed = candleStickFeed;

    System.out.println("Feed Size This Thread = " + candleStickFeed.getSize());

    Platform.runLater(new Runnable(){
        
        @Override
        public void run(){
            
            System.out.println("Feed Size JavaFX Thread = " + candleStickFeed.getSize());
            updateChart();
        }
    });
}

The program will sometimes output

Feed Size This Thread = 5

Feed Size JavaFX Thread = 5

Which is what I would expected. But it also sometimes outputs

Feed Size This Thread = 5

Feed Size JavaFX Thread = 0

Any help would be greatly appreciated. I new to using multiple threads so not sure what I'm doing really. I have looked for different answers but couldn't find any. Thank you

Upvotes: 0

Views: 508

Answers (2)

Solomon Slow
Solomon Slow

Reputation: 27190

This is a supplement to @Simon's answer.

Your problem is not about "passing a variable." Your runLater(...) task apparently is getting the value of the variable. The problem is that the value is a reference to a mutable object, and that object sometimes is modified in between the time when the task is created and the time when the task is executed.

Simon's suggestion boils down to this: Give the new task its own private copy of whatever information it will need from the CandleStickFeed instance, and let it work exclusively from that private copy.

Upvotes: 4

Simon
Simon

Reputation: 3284

Try to extract the relevant information from the candleStickFeed, and pass that structure into a Runnable subclass.

public void updateScene(CandleStickFeed candleStickFeed) {
    CandleStickData data = new CandleStickData(candleStickFeed);
    Platform.runLater(new ChartUpdateRunnable (data));
}

private class CandleStickData {
    private double[] numbers; // or whatever you need
    CandleStickData (CandleStickFeed candleStickFeed) {
        this.numbers = new double[candleStickFeed.getSize()];
        // TODO: populate the data structure
    }
}

private ChartUpdateRunnable implements Runnable {
    private CandleStickData data;
    ChartUpdateRunnable(CandleStickData data) {
        this.data = data;
    }
    @Override
    public void run(){
        System.out.println("Feed Size JavaFX Thread = " + data);
        updateChart();
    }
} 

The principle is to not pass around a feed class which might change state often, but extract an immutable state object, and pass that to a runnable class instance for update.

Upvotes: 6

Related Questions