Некорректное изменение значений при работе с потоками

Создаю n независимых потоков, после выполнения метода transaction должно происходить изменение значений (c одного счета должны уходить деньги на другой), но после выполнения, значения не изменяются. По умолчанию в методе save добавляю на каждый счет 10000. Должно произойти 9 транзакций и после этого программа должна завершится.

Сущность Account:

@Entity
@Table
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public class Account {
    @Id
    @Column(name = "id")
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Getter
    private long id;

    @Column(name= "money")
    @Getter
    @Setter
    private int money;

    public static AtomicInteger numberTransaction = new AtomicInteger();

    public int withdrawal(int value) {
       return money += value;
    }

    public int send(int value) {
       return money -= value;
    }
}

Репозиторий:

public interface AccountRepository extends CrudRepository<Account,Long> {

}

Сервис:

    @Service
public class AccountService extends Thread {
    private final AccountRepository accountRepository;

    public AccountService(AccountRepository accountRepository) {
        this.accountRepository = accountRepository;
    }

    public Iterable<Account> findAllAccount() {
        return accountRepository.findAll();
    }

    public Account save(Account account) {
        account.setMoney(10000);
        return accountRepository.save(account);
    }

    public Long countAccount() {
        return accountRepository.count();
    }

    public Account update(Account category) {
        return accountRepository.save(category);
    }

    public void delete(Long id) {
        accountRepository.deleteById(id);
    }


    public void transaction(Long accountIdOne, Long accountIdTwo, int value) {
        Account accountOne = accountRepository.findById(accountIdOne).orElseThrow();
        Account accountTwo = accountRepository.findById(accountIdTwo).orElseThrow();
        synchronized (accountOne) {
            synchronized (accountTwo) {
                accountOne.withdrawal(value);
                this.update(accountOne);
                accountTwo.send(value);
                this.update(accountTwo);
            }
        }
    }

    public void test() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (Account.numberTransaction.get() < 10) {
                    int sleep = (int) (Math.random() * (2000 - 1000)) + 1000;
                try {
                   transaction(1L, 2L, 1000);
                   Account.numberTransaction.incrementAndGet();
                   Thread.sleep(sleep);
                    } catch (InterruptedException exception) {
                        exception.printStackTrace();
                    }
                }
            }
        }).start();
    }
}

Тест:

@SpringBootTest
class AccountTransferApplicationTests  {
    @Autowired
    private AccountService accountService;


    @Test
    void contextLoads() throws InterruptedException {
        Account account = new Account();
        Account account1 = new Account();

        accountService.save(account);
        accountService.save(account1);



        for(int i = 0; i < accountService.countAccount(); i++) {
            accountService.test();
            accountService.join();

        }
    }

}

Ответы (1 шт):

Автор решения: Денис Старакожев

Не буду говорить на сколько вся задумка объединить управление потоками, транзакциями и данными в одном сервисе выглядит сомнительно.

Скажу почему не работает так как вы задумали.

  1. Ваш AccountService наследует Thread и является потоком.
  2. метод test() вызывает ваш метод transaction() создавая новый поток.
  3. Вы запускаете логику транзакции в одном потоке (new Thread() в методе test), а ждете выполнения другого потока (accountService), по этому фактически не дожидаетесь завершения логики, по этому и данные не сохраняются
→ Ссылка