Рабочие потоки ExecutorService ThreadPool не будут вызывать методы с переменными элементами - PullRequest
1 голос
/ 19 мая 2019

У меня есть класс с именем WatermarkEventProcessorService, который содержит несколько переменных-членов с автосвязью.WatermarkEventProcessorService передается в FixedThreadPool в качестве задачи.

Проблема в том, что рабочие потоки ThreadPool не вызывают методы WatermarkEventProcessorService с автоматически подключаемыми переменными.Как только метод элемента autowired вызывается, рабочий поток просто останавливает обработку.

Ниже приведен метод, который создает ThreadPool:

 public void processWatermarkEventObjects(List<WatermarkEventObject> waterEventObjectList) {    

        ExecutorService executor = Executors.newFixedThreadPool(1);

        for (WatermarkEventObject watermarkEventObject : waterEventObjectList) {
            executor.submit(new WatermarkEventProcessorService(watermarkEventObject));
        }

        executor.shutdown();
    }

Ниже указано WatermarkEventProcessorService:

@Service
public class WatermarkEventProcessorService implements Runnable {

    @Autowired
    private WatermarkEventObject watermarkEventObject;

    @Autowired
    private ApplicationAPIService apiService;

    public WatermarkEventProcessorService(WatermarkEventObject watermarkEventObject) {
        this.watermarkEventObject = watermarkEventObject;
    }

    private boolean prismIdExists(WatermarkEventObject watermarkEventObject) {

        return watermarkEventObject.getPrismId() != null && watermarkEventObject.getPrismId().length() > 0 ? true
                : false;
    }

    public ApplicationRecord findApplicationRecordByPrismId(String prismId) {

        System.out.println("Inside findApplicationByPrismId");
        // Prism Id Exists in Table: Application?
        // Call RESTful Web Service to retrieve Application record by Prism Id from
        // MySQL database.

        System.out.println("about to invoke apiService.getApplicationByPrismId()");
        ApplicationRecord applicationRecord = apiService.getApplicationByPrismId(prismId); //doesn't get invoked for some reason...
        System.out.println("returned from apiService.getApplicationByPrismId()");

        return applicationRecord;
    }

    @Override
    public void run() {
        System.out.println("Starting Processor thread.");

        // Validate that PrismId exists, else write to error log file, for now.
        // TODO: Please note that we will need to look up MOTS info & create new
        // Application.
        if (prismIdExists(watermarkEventObject)) {

            System.out.println("within the if block");
            // Gets the application record for the given prism id, or creates
            // a new application record in the database if we dont have one
            ApplicationRecord appRecord = findApplicationRecordByPrismId(watermarkEventObject.getPrismId());
            System.out.println("Returned from findApplicationByPrismId");
        }

        System.out.println("Completed Processor thread.");
    }
}

Когда я запускаю приложение, оно выполняется просто отлично, но последний достигнутый оператор печати «собирается вызвать apiService.getApplicationByPrismId ()».Следующий оператор журнала - «возвращенный из apiService.getApplicationByPrismId ()» никогда не получает выходных данных и никогда не генерирует исключение.

Я также добавил оператор печати в самом начале apiService.getApplicationByPrismId(prismId) метода, но это также никогда не выполняется.Это означает, что метод никогда не вызывается:

Ниже приведен метод, который не вызывается (но должен быть):

@Cacheable("applications")
    public ApplicationRecord getApplicationByPrismId(String prismId) {

        System.out.println("inside getApplicationByPrismId"); //never gets printed
        ApplicationRecord applicationRecord = null;
        ApplicationResults resultList = new ApplicationResults();
.
.
.
}

Ниже приведены соответствующие журналы консоли:

Starting Processor thread. within the if block Inside findApplicationByPrismId about to invoke apiService.getApplicationByPrismId() Starting Processor thread. within the if block Inside findApplicationByPrismId about to invoke apiService.getApplicationByPrismId() Starting Processor thread. within the if block Inside findApplicationByPrismId about to invoke apiService.getApplicationByPrismId()

Что здесь не так?

Ответы [ 2 ]

2 голосов
/ 19 мая 2019

Вы должны передать объект, созданный контейнером Spring, чтобы позволить Spring управлять вашими зависимостями:

@Autowired
WatermarkEventProcessorService watermarkEventProcessorService; //injection by field for brevity

public void processWatermarkEventObjects(List<WatermarkEventObject> waterEventObjectList) {    

    ExecutorService executor = Executors.newFixedThreadPool(1);

    for (WatermarkEventObject watermarkEventObject : waterEventObjectList) {
        executor.submit(watermarkEventProcessorService);
    }

    executor.shutdown();
}
2 голосов
/ 19 мая 2019

Spring bean-компоненты - это bean-компоненты, которые в основном управляются средой Spring.

@Autowired и другие аннотации влияют только (только на смысл) для бобов весны.

Управление Spring означает, что Spring сам по себе создает объекты (вызывая new)

Но это не то, что происходит здесь во фрагменте кода:

 for (WatermarkEventObject watermarkEventObject : waterEventObjectList) {
        executor.submit(new WatermarkEventProcessorService(watermarkEventObject));
 }

Здесь WatermarkEventProcessorService создается самим приложением, поэтому Spring не знает, что это bean-компонент, и, следовательно, не выполняет никаких автоматических подключений к нему

С точки зрения решения:

Обратите внимание, что вы уже передали экземпляр WatermarkEventObject, несмотря на то, что аннотация с автопроводкой помещена в соответствующее поле в классе WatermarkEventProcessorService Так почему бы вообще не удалить @Autowired и просто передать дополнительный параметр, что делает этот класс неуправляемым вообще.

Если вам нужно, чтобы весной этот класс управлялся, рассмотрите возможность использования Scope Prototype Scope и создавайте подобные объекты по запросу с каким-либо провайдером.

...