1

I have a method where am calling executor.sumbit() as below,

List<Stock> stockList ;

        executor.submit( ()-> {
            stockList = stockService.getAllStocks();
        });

I'm facing "Local variable stockList defined in an enclosing scope must be final or effectively final" compiler error. I tried solve with help of Google but no luck :-(

Any help or suggestion appreciated, thanks!

prostý člověk
  • 909
  • 11
  • 29
  • @TimBiegeleisen - I see the extraction but slightly different in my case. – prostý člověk May 09 '19 at 17:09
  • You can't assign to a local variable from within a lambda expression. Make the List an instance field and ensure you're not in a static context when you access it (unless it's qualified with a reference of course). – WJS May 09 '19 at 17:34
  • `List stockList = executor.submit(() -> stockService.getAllStocks()) .get();`, but of course, this will destroy the benefit of asynchronous computation. You have to decide *when* to query the result via [`get()`](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Future.html#get--). Before that, you *must not* try to use the result anyway. – Holger May 09 '19 at 17:58

1 Answers1

1

Since stock service returns a list, why not just do the following:

    List<Stock> stockList = new ArrayList<>();

    executor.submit( ()-> {
        List<Stock> temp = stockService.getAllStocks());
        stockList.addAll(temp);
        //now that it's copied, submit to the executor.
        return temp;
    });

Since stockList is a reference, you are not changing the reference but only what stockList refers to. So you would not be violating the effectively final requirement. Note: Since the executor service returns immediately there may be a time delay before the list gets populated.

WJS
  • 36,363
  • 4
  • 24
  • 39
  • I tried with this approach as well, but returns empty list for some reason. – prostý člověk May 09 '19 at 19:10
  • It was the executor service. It returns immediately before the list gets filled. I waited to seconds and it filled it. This is similar to what @Holger was talking about. So I will edit my answer to reflect this. – WJS May 09 '19 at 19:35
  • WJS - Yest that's true, it works, Thanks! – prostý člověk May 10 '19 at 05:54
  • @WJS you’ve been lucky if waiting for a second gave you the desired result, but since waiting for an elapsed time does not establish a so called *happens-before* relationship between the `addAll` operation made in another thread and your subsequent use of the list, it is not thread-safe, regardless of how long you wait. There is no way around using the `Future` returned by `submit`, to detect the completion of the job correctly, establishing the necessary thread safety. – Holger May 10 '19 at 12:11