0

I have what most likely is a dumb question regarding thread safety. I have a ENUM class where I have valuesof defined like so:

public enum ThirdPartyContentSource {
    DEV_TO("DevTo"),
    MEDIUM("Medium"),
    HASH_NODE("HashNode");

    private String thirdPartyText;

    ThirdPartyContentSource(String text) {
        this.thirdPartyText = text;
    }

    public String getText() {
        return this.thirdPartyText;
    }

    public static String valueOfCode(String thirdPartyCode) throws IllegalArgumentException {
        ThirdPartyContentSource text = Arrays.stream(ThirdPartyContentSource.values())
                .filter(val -> val.name().equals(thirdPartyCode))
                .findFirst()
                .orElseThrow(() -> new IllegalArgumentException("Unable to resolve ThirdPartyCode: " + thirdPartyCode));

        return text.getText();
    }
}

my question is, if two threads call the the valueOfCode() method at the same time is there any thread safety concerns?

Many thanks

Luiggi Mendoza
  • 85,076
  • 16
  • 154
  • 332
MetaCoder
  • 368
  • 5
  • 22
  • 3
    Why not use the `valueOf()` method, see https://stackoverflow.com/questions/604424/how-to-get-an-enum-value-from-a-string-value-in-java? – Progman Feb 20 '23 at 21:47
  • Presumably, @Progman, because the strings the OP wants to convert into enum instances are different from the names of the instances. They may well not have any better way to reconcile their requirements for external representation with their code conventions for enum names. – John Bollinger Feb 20 '23 at 22:10
  • @JohnBollinger Except the OP does `val.name().equals(thirdPartyCode)`, which compares the input string exactly. Seems like that whole method could be replaced with `ThirdPartyContentSource.valueOf(thirdPartyCode).getText()`. I assume the intention is to be able to convert `"DEV_TO"` to `"DevTo"` and such, though that's just a guess. – Slaw Feb 20 '23 at 22:35
  • Fair observation, @Slaw. I am, of course, assuming that where the OP wrote `val.name().equals(thirdPartyCode)` they meant `val.getText().equals(thirdPartyCode)`. If that's incorrect then the `valueOf()` method they get for free would indeed be a better choice than a hand-rolled work-alike. – John Bollinger Feb 20 '23 at 22:52

2 Answers2

1

There won't be any thread safety issue since you're not modifying any data in there. There won't be a race condition or anything like that.

Luiggi Mendoza
  • 85,076
  • 16
  • 154
  • 332
0

tl;dr

Mark thirdPartyText as final. Then you’re thread-safe.

Details

The enum objects themselves (DEV_TO, MEDIUM, HASH_NODE) are all instantiated when their enum class loads. So no thread-safety issues there.

Your enum class carries state, the thirdPartyText. The content of the field is immutable (String). That is good, as being immutable eliminates some concurrency issues.

The only problem I see is if the object reference were changing during runtime, if you were to replace one String object with another String object. Apparently you intend that this state does not change during runtime. You can enforce that by declaring the class member field to be final. Being final means that another object cannot be assigned to that reference variable.

private final String thirdPartyText;  // Make this field `final`. 

Your valueOfCode method loops through the enums (via .values call), which does not change during runtime. So no thread-safety problem there.

And your valueOfCode method accesses the thirdPartyText field which we fixed by making final, so those values are not changing during runtime. So no thread-safety problem there.

Your intention for valueOfCode is not clear — see Comments posted on the Question. But I don't see a thread-safety issue there.

While I am not a concurrency expert, you code looks thread-safe to me, after making that final change.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154