πŸ–₯️ μ΄μ»€λ¨ΈμŠ€ν”„λ‘œμ νŠΈ/✏️ TIL

[TIL] λ‹€μ‹œ μ‹œμž‘ν•΄λ³΄λŠ” ν”„λ‘œμ νŠΈ TIL 14일차..

carrot0911 2025. 5. 4. 21:31

🌞 μ˜€λŠ˜μ€ μ–΄λ–€ ν•˜λ£¨μ˜€μ§€..

μ˜€λŠ˜μ€ ν•˜λ£¨ 쒅일 ν”Όκ³€ν–ˆλ˜ ν•˜λ£¨μ˜€λ‹€.

μ˜€μ „μ—λŠ” λΆ€λͺ¨λ‹˜ λ”°λΌμ„œ 할아버지, ν• λ¨Έλ‹ˆ μ‚°μ†Œμ— κ°€μ„œ μž‘μ—…μ„ ν•˜κ³  μ˜€ν›„ 5μ‹œμ―€ 집에 도착할 수 μžˆμ—ˆλ‹€.
그리고 μ”»κ³  λ‚˜μ„œ μ™Έν• λ¨Έλ‹ˆλŒμœΌλ‘œ κ°”λ‹€. ν•˜μ§€λ§Œ λ‚˜λŠ” ν•΄μ•Ό ν•  λΆ„λŸ‰μ΄ μžˆμ—ˆκΈ°μ— μ§‘ μ•ž μŠ€λ²…μ— κ°€μ„œ ν…ŒμŠ€νŠΈ μ½”λ“œ μž‘μ„±μ„ λ§ˆλ¬΄λ¦¬ν–ˆλ‹€.

λ§₯뢁을 사고 처음으둜 μΉ΄νŽ˜μ— κ°€μ„œ μž‘μ—…μ„ ν–ˆλŠ”λ°, 생각보닀 λŠλ‚Œμ΄ 더 μ’‹μ•˜λ‹€.
λ‹€λ“€ μ΄λž˜μ„œ λ§₯뢁을 λ“€κ³  μΉ΄νŽ˜μ— κ°€μ„œ μž‘μ—…μ„ ν•˜λŠ” 건가 γ…Žγ…Žγ…Žγ…Žγ…Ž

λ™μ‹œμ„± μ œμ–΄ ν…ŒμŠ€νŠΈ μ½”λ“œλŠ” λ‹¨μœ„ ν…ŒμŠ€νŠΈλ‘œ 확인할 μˆ˜κ°€ μ—†μ—ˆκ³ , 톡합 ν…ŒμŠ€νŠΈλ‘œλ§Œ 확인이 κ°€λŠ₯ν•˜λ‹€λŠ” 것을 μ•Œκ²Œ λ˜μ—ˆλ‹€!
아직 ν…ŒμŠ€νŠΈ μ½”λ“œμ— λ―Έν‘ν•΄μ„œ 더듬더듬 μ—΄μ‹¬νžˆ μ§°κ³ , ν…ŒμŠ€νŠΈ μ½”λ“œμ— λŒ€ν•œ 곡뢀가 더 ν•„μš”ν•˜λ‹€κ³  λŠκΌˆλ‹€. 아직 곡뢀해야 될 것듀이 산더미ꡰ...

κ·Έλž˜λ„ ν…ŒμŠ€νŠΈ μ½”λ“œλ‘œ λ™μ‹œμ„± μ œμ–΄κ°€ 잘 λ™μž‘ν•˜λŠ” 것을 ν™•μΈν•˜κ³  ν•˜λ£¨λ₯Ό λ§ˆλ¬΄λ¦¬ν•΄μ„œ 닀행이닀.

 

πŸ’‘ μƒˆλ‘­κ²Œ μ•Œκ²Œ 된 λ‚΄μš©μ€ 뭐가 μžˆλ”λΌ..?!

λ™μ‹œμ„± μ œμ–΄ ν…ŒμŠ€νŠΈ μ½”λ“œ

더보기
@Slf4j
@SpringBootTest
@AutoConfigureMockMvc
public class CouponServiceConcurrencyTest {

    @Autowired
    private CouponService couponService;

    @Autowired
    private MemberRepository memberRepository;

    @Autowired
    private MemberCouponRepository memberCouponRepository;

    @Autowired
    private CouponRepository couponRepository;

    private Long couponId;
    private final int MAX_ISSUE_COUNT = 10;
    private final int THREAD_COUNT = 32;

    @BeforeEach
    void setUp() {
        Coupon coupon = Coupon.of(
            "ν…ŒμŠ€νŠΈ 쿠폰", 5000, MAX_ISSUE_COUNT,
            LocalDate.now(), LocalDate.now().plusDays(7));

        couponRepository.save(coupon);
        couponId = coupon.getId();

        for (int i = 0; i < THREAD_COUNT; i++) {
            Member member = Member.of(
                "user" + i + "@email.com", "1234", "ν…ŒμŠ€νŠΈ μ‚¬μš©μž " + i, 27,
                String.format("010%08d", i), Authority.CUSTOMER, GenderType.M);
            memberRepository.save(member);
        }
    }

    @Test
    void λ™μ‹œμ—_100λͺ…이_쿠폰을_μš”μ²­ν•˜λ©΄_쀑볡없이_10λͺ…λ§Œ_μΏ ν°λ°œκΈ‰() throws InterruptedException{
        // given
        ExecutorService excutor = Executors.newFixedThreadPool(THREAD_COUNT);
        CountDownLatch latch = new CountDownLatch(THREAD_COUNT);

        List<Member> memberList = memberRepository.findAll();

        long start = System.currentTimeMillis();

        // when
        for (Member member : memberList) {
            excutor.submit(() -> {
                try {
                    couponService.issueCoupon(couponId, member.getId());
                } catch (Exception ignored) {

                } finally {
                    latch.countDown();
                }
            });
        }

        latch.await();

        long end = System.currentTimeMillis();

        // then
        long count = memberCouponRepository.count();
        assertEquals(MAX_ISSUE_COUNT, count);

        log.info("βœ… Thread: {}λͺ… | ⏱ Duration: {}ms | 🎟 Issued: {}개", THREAD_COUNT, end - start, count);
    }
}

 

πŸ—“οΈ 내일은 뭐 ν•˜μ§€?!

βœ”οΈ μŒ“μΈ ν”Όλ‘œ ν’€κΈ°...
βœ”οΈ νœ΄μ‹..