Исключение NullPointer при использовании многопоточности в Spring

Я новичок в многопоточности. Я пытался сохранить список объектов в базе данных sql, используя репозиторий crud. но я получаю исключение нулевого указателя в операции сохранения. Ниже мой код и исключение. Класс потока

public class PrescriptionThread implements Runnable{
  private MedicineService medServ = new MedicineService();
  private  Presciption pres ;

  public PrescriptionThread(Presciption pres) {
    this.pres = pres;
  }

  @Override
  public void run() {
    medServ.savePrescription(pres);
    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
  }
}

Класс обслуживания

@Service
public class MedicineService {

@Autowired
private PrescriptionRepository presRepo;

public void storePrescription(List<Presciption> payload) {

    ExecutorService executorService = Executors.newFixedThreadPool(5);
    for (Presciption presciption : payload) {
        Runnable runnable = new PrescriptionThread(presciption);
        executorService.execute(runnable);
    }
    executorService.shutdown();

    while(!executorService.isTerminated()) {}
}


public synchronized void savePrescription(Presciption pres) {
        presRepo.save(pres);
}
}

Репозиторий

@Repository
public interface PrescriptionRepository extends CrudRepository<Presciption, Integer> {

}

Я получаю исключение в presRepo.save (прес);

Exception in thread "pool-1-thread-3" Exception in thread "pool-1-thread-1" Exception in thread "pool-1-thread-2" java.lang.NullPointerException
at com.cerner.api.service.MedicineService.savePrescription(MedicineService.java:86)
at com.cerner.api.util.PrescriptionThread.run(PrescriptionThread.java:16)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:834)

Если я не использую поток и просто скажу

for (Presciption presciption : payload) {
        presRepo.save(pres);
    }

Он работает нормально, и я могу сохранить его в БД. Но я хочу реализовать поток. Заранее спасибо.

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
0
1 611
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

в результате здесь:

private MedicineService medServ = new MedicineService();

экземпляр 'medServ' был управлением IOC Spring, если вы 'новый', возможно, не получите экземпляр 'PrescriptionRepository', потому что это был '@Autowire', он будет генерировать NPE при вызове presRepo.save(pres). но если вы не используете Thread, это означает, что экземпляр не является новым для вас, поэтому он может работать нормально

Если я не понял неправильно. Вы хотите сказать, что если я хочу использовать Thread, мне нужно создать объект MedicineService с помощью @Autowired?

Sam 06.12.2018 04:04

Но если я это сделаю, внутри метода запуска будет исключение нулевого указателя. для medServ.savePrescription (pre); поскольку с помощью Autowired мы не можем доставить объект туда. Пожалуйста, предложите

Sam 06.12.2018 04:10

открытый класс PrescriptionThread реализует Runnable {private MedicineService medServ; частный Presciption pres; public PrescriptionThread (Presciption pres, MedicineService MedicineService) {this.pres = pres; this.medServ = MedicineService; } @Override public void run () {medServ.savePrescription (pres); попробуйте {Thread.sleep (1000); } catch (InterruptedException e) {e.printStackTrace (); }}}

black.he 06.12.2018 06:33

Спасибо. Я меняю конструктор потока и передаю даже объект службы. и он работает нормально.

Sam 06.12.2018 09:15
Ответ принят как подходящий

Я изменил свой класс потока, как показано ниже, и мне удалось получить компонент.

public class PrescriptionThread implements Runnable{
private MedicineService medServ;// = new MedicineService();
private  Presciption pres ;

public PrescriptionThread(Presciption pres, MedicineService medicineService) {
this.pres = pres;
this.medServ = medicineService;
}

@Override
public void run() {
medServ.savePrescription(pres);
try {
    Thread.sleep(1000);
} catch (InterruptedException e) {
    e.printStackTrace();
}
}
}

Другие вопросы по теме