#java #spring #java.util.concurrent
#java #spring #java.util.concurrent
Вопрос:
Читая исходный код SpringRetry, я натыкаюсь на этот фрагмент кода:
private static class AnnotationMethodsResolver {
private Class<? extends Annotation> annotationType;
public AnnotationMethodsResolver(Class<? extends Annotation> annotationType) {
this.annotationType = annotationType;
}
public boolean hasAnnotatedMethods(Class<?> clazz) {
final AtomicBoolean found = new AtomicBoolean(false);
ReflectionUtils.doWithMethods(clazz,
new MethodCallback() {
@Override
public void doWith(Method method) throws IllegalArgumentException,
IllegalAccessException {
if (found.get()) {
return;
}
Annotation annotation = AnnotationUtils.findAnnotation(method,
annotationType);
if (annotation != null) { found.set(true); }
}
});
return found.get();
}
}
Мой вопрос в том, почему здесь используется AtomicBoolean
в качестве локальной переменной? Я проверил исходный код RelfectionUtils.doWithMethods()
и не нашел там никакого вызова параллелизма.
Комментарии:
1. Ну, параллелизм — это одна из причин, по которой вы бы использовали что-то вроде
AtomicBoolean
, так что, возможно, вам следует проверить еще раз.2. Извините, я действительно не могу найти никакого параллелизма в org.springframework.util. ReflectionUtils. doWithMethods,
3. Вам нужно найти способы использования этого класса и посмотреть, содержался ли этот объект когда-либо в многопоточном контексте.
4. «найдено» — это локальная переменная, а «Локальные переменные в Java потокобезопасны». вызов метода ANNOTATIONMETHOD решателя в многопоточном контексте не вызовет никаких проблем с локальной переменной «найдено», насколько мне известно
5. Я нашел причину, я забыл правило «локальная переменная, к которой обращается внутренний класс, должна быть объявлена как final» ….. в любом случае, спасибо за комментарий. хорошего дня!
Ответ №1:
Каждый вызов hasAnnotatedMethods
получает свой собственный экземпляр found
, поэтому контекст, из которого hasAnnotatedMethods
вызывается, не имеет значения.
Возможно, что ReflectionUtils.doWithMethods
вызывает doWith
метод из нескольких потоков, для чего потребуется doWith
потокобезопасность.
Я подозреваю, что это AtomicBoolean
просто используется для возврата значения из обратного вызова, и это boolean[] found = new boolean[1];
сошло бы так же хорошо.
Комментарии:
1. да, я так думаю, но я не могу найти никакого параллелизма в ReflectionUtils. doWithMethods. Я только что понял правило, согласно которому «найдено» должно быть объявлено окончательным, когда к нему обращается внутренний класс. но я все еще не могу понять, почему в методе doWith есть «if (found.get()) » прямо в
2.
if(found.get())
Это для короткого замыкания, потому чтоdoWithMethods
будет перебирать все методы, но вы можете остановиться, как только найдете один. Это не остановит цикл, но последующие итерации будут просто пустыми.