본문 바로가기
개발/Java

[Java] Thread(스레드) - 생성, 실행, 종료 하기 , 에러 해결

by 코딩하는 흰둥이 2023. 5. 13.
반응형

SpringBoot 를 실행 중에 웹 상에서 버튼을 이용하여

일련의 작업(임의의 테이블의 update 작업 , 일괄 Email 전송, Excel upload 등등)들을 껐다 켰다 할 수 있을까

라는 생각을 하게 되었고 Batch 와 Scheduler 를 이용해 보았지만 따로 제어하기가 힘들다고 생각됐다

그래서 Thread를 이용해보았고 내가 원하던 대로 동작은 하고 있지만

많은 작업을 시도해 보지 않아서 어디까지 뻗지 않고 가능한지 잘 모르겠다

 

TestThread.class
public class TestThread extends Thread{

    public void run() {
        while(true){
            try {
                // Test를 위해 2초마다 출력되도록 함
                Thread.sleep(2000);
                System.err.println("테스트 Thread 실행 중");
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

 

 

TestController.class
@Controller
public class UserController {

    // Test thread 
    TestThread tt = new TestThread();

    @GetMapping("/login")
    public String loginPage() throws Exception{
        System.err.println("Login Page~~~~");
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        // 로그인 정보가 없으면 loginPage 로 있으면 / 메인페이지로
        if (authentication instanceof AnonymousAuthenticationToken)
            return "loginPage";
        return "redirect:/";
    }


    // Thread 실행 메서드 
    @GetMapping("/start")
    public void start() throws Exception{
        System.err.println("Thread 시작");
        tt.start();
    }
    
    // thread 종료 메서드
    @GetMapping("/stop")
    public void stop() throws Exception{
        System.err.println("Thread 종료");
        tt.interrupt();
    }
    
}

 

 

실행

localhost 화면

 

 

 

localhost:9090/start 를 했다가 다시 login 화면으로 돌아왔을때 

log가 어떻게 찍히는지를 확인

 

페이지를 생성하지 않았기 때문에 에러 로그도 같이 찍힘 문제x

 

로그인 페이지로 이동했어도 2초마다 로그가 찍히는 것을 확인 가능

 

 

/stop 을 하였을때 종료

 

 

 

 

Thread 실행에는 run()  start() 가 있는데 둘 다 실행을 하지만 동작 원리가 다르다

 

run() 은 단순히 메서드를 호출하는 것이며 Single Thread 하나의 thread 가 끝나야 다음 thread 가 실행된다

start() 는 새로운 Thread가 작업을 실행하게 되어 새로운 호출 스택을 생성한 뒤 run()을 호출하여 Multi Thread 로 동시에 실행된다(동시라고는  했지만 실제론 동시에 진행되지는 않는다)

 

 

 

 

오류

localhost:9090/stop 을 하고 다시 /start를 하니 IllegalThreadStateException 오류가 발생했다

해당 Exception 을 찾아보니 한번 실행이 종료된 Thread 는 다시 실행 할 수 없고

다시 실행을 시켰을 때 IllegalThreadStateException 가 발생한다고 한다

 

방법은 start 메서드를 사용할 때마다 Thread를 생성해주면 된다

 

@Controller
public class UserController {

    // Test thread 
    TestThread tt = new TestThread();
    
    ->>>
    
    @Controller
public class UserController {

    // Test thread 
    TestThread tt;

Controller 상단에서 선언하고 객체를 생성했었는데

객체를 선언만 시킨다

 

    @GetMapping("/start")
    public void start() throws Exception{
        System.err.println("Thread 시작");
        tt = new TestThread();
        tt.start();
    }

/start 메서드에서 객체를 생성하면 Thread가 동작을 다하고 끝나거나

중간에 종료를 시킨 후 에도 /start 메서드를 통해 다시 동작 할 수 있다 

 

 

 

 

웹상에서는 url을 통해 기능이 동작하기 때문에 동시에 여러 작업을 할 수 없다

만약 사이트에서 이메일을 전송한다고 했을 때

한 두명~ 수십명 정도야 조금만 기다리면 바로 전송이 되지만 

 

100만명에게 이메일을 작성하고 전송을 한다면

전송 동작이 끝날 때까지 아무것도 할 수 없고 멍하니 모니터만 바라봐야 할 것이다

 

이런 상황 혹은 지속적으로 어떤 동작이 계속 실행되어 있어야 하는 상황에 사용 할 수 있을까 하여 글을 남겨 둔다

 

 

댓글