Почему здесь используется Atomic?

#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 будет перебирать все методы, но вы можете остановиться, как только найдете один. Это не остановит цикл, но последующие итерации будут просто пустыми.