Это не полностью потокобезопасно - потому что другой поток может изменять тот же массив, который был передан в аргументе для параметра strings
. Это не совсем очевидно из-за использования вами varargs, но эффективно (с точки зрения безопасности потоков) сигнатура метода просто:
public static String cat(String[] strings)
Это не вызовет никаких исключений, но вы можете не увидеть последние значения в массиве.
В качестве другой альтернативы, вы могли бы увидеть что-то неожиданное, если бы действительно увидело изменение. Например, предположим, что мы передаем только однозначный массив, где значение изначально равно «x»:
public static String cat(final String ... strings) {
...
...
final StringBuilder sb = new StringBuilder(totLength);
for (int i = 0; i < size; i++) {
// strings[0] is currently "x"
if (strings[i] != null) {
// But now another thread might change it to null!
// At that point we'd get "null" as output
sb.append(strings[i]);
}
}
return sb.toString();
}
Другими словами, хотя вы, вероятно, ожидаете, что увидит "x" или "" в результате, вы можете увидеть "null". Чтобы это исправить, вы можете прочитать каждое значение из массива просто один раз :
final StringBuilder sb = new StringBuilder(totLength);
for (int i = 0; i < size; i++) {
String value = strings[i];
if (value != null) {
sb.append(value);
}
}
Вы по-прежнему можете видеть массив, который на полпути изменяется (например, если один поток меняется {"x", "y"}
на {"a", "b"}
, вы можете увидеть «xb» в результате), но вы не получите поддельные » нуль».