코딩하렴

Stack Unwinding 스택풀기 :: 스레드 반복, 람다식 등 활용

by 으렴

다음의 코드를 봅시다요

 

	public static void main(String[] args) {
		System.out.println(1);
		try {
			Thread.sleep(2000); // Blocking // exception발생try catch
			System.out.println("냥냥");
		} catch (InterruptedException e1) {
		}
		System.out.println(2);

		A a = new A();
		a.func01();
	}

AOP Aspect Oriented Programming 관점 지향 프로그래밍

 

출력문 1을 실행해두고 나머지 관심있는 부분만 다루는 것이라고 생각하면된다.

 

thread.sleep으로 blocking이 걸리게 된다.

 

		System.out.println(1);			//1
		try {
			Thread.sleep(2000);
			System.out.println("냥냥");
		} catch (InterruptedException e1) {
		}
		System.out.println(2);
        
        System.out.println(1);			//2
		try {
			Thread.sleep(2000);
			System.out.println("댕댕");
		} catch (InterruptedException e1) {
		}
		System.out.println(2);
        
        System.out.println(1);			//3
		try {
			Thread.sleep(2000);
			System.out.println("찎찎");
		} catch (InterruptedException e1) {
		}
		System.out.println(2);

이것을 3번 반복해보자

 

이러한 코드를 줄일수는 없을까?

 

interface T {
	public void func01();
}

이렇게 인터페이스를 생성하자

 

그리고 이것을 호출하는 메소드 func02를 만든다.

class A {
	public void func02(T t) {
		System.out.println(1);
		
		t.func01();
		
		System.out.println(2);
	}
    
}

출력문을 출력하고 func을 생성해 준다.

	public void func() throws Exception { 
		func02(new T() {
			public void func01() throws Exception {
				Thread.sleep(2000);
				System.out.println("냥냥");
			}
		});

		func02(new T() {
			public void func01() {
				try {
					Thread.sleep(2000);
				} catch (Exception e) {

				}
				System.out.println("멍멍");
			}
		});
        
		func02(new T() {
			public void func01() {
				Thread.sleep(2000);
				System.out.println("찎찎");
			}
		});
	}

 

마지막 T 객체 생성은 에러가 날 것이다 에러처리를 하지 않았기 때문이다.

 

트라이캐치를 써도 좋고 에러를 던지는 것으로 처리해도 좋다

 

하지만 밑에서 throws를 사용하여 스택풀기를 시도했기 때문에 일단은 throws로 남겨두자

 

	public static void main(String[] args) {

		A a = new A();
		a.func();

	}

이렇게 해서 A객체를 생성하여부르면 완성이다.

 

이 코드를 람다식으로 수정하고 에러의 책임을 다른곳으로 돌려 스택풀기를 시도해보자

 

이제 메인을 건드릴 일은 없다.

 

자 그럼 func을 람다식으로 바꿔보자

 

	public void func() {
		func02(() -> {
			Thread.sleep(2000);
			System.out.println("냥냥");
		});

		func02(() -> {
			Thread.sleep(2000);
			System.out.println("멍멍");
		});
		func02(() -> {
			Thread.sleep(2000);
			System.out.println("냥냥");
		});

	}

 

여기서 이상한점!

 

위에 처음 적은 코드와 다르게 트라이캐치를 사용하지 않았다.

 

스레드를 사용하려면 예외처리 해줘야한담시?

 

ㅇㅇ.. 다른 곳으로 옮겨주었다.

 

	public void func02(T t) {
		System.out.println(1);
		try {
			t.func01();
		} catch (Exception e) {

		}
		System.out.println(2);
	}

여기는 트라이 캐치를썼네? 여기로 돌렸나? 맞다.

 

근데 그전에 이미 throws Exception을 처리를 해주고 여기 한번만 트라이캐치를 했다.

 

interface T {
	public void func01() throws Exception;
}

이곳 인터페이스에서 에러가 발생하면 던지세요라고 명시해두어서

 

굳이 3번 트라이캐치를 사용하지 않아도 에러 해결이 가능하다.

 

이러한 것을

 

스택풀기 Stack Unwinding라고 한다.

 

 

스택 풀기란어떠한 함수 내에서 throw절이 실행되면 예외가 발생한다는 뜻이다.

 

예외처리를 위한 try-catch문이 없는 경우 예외처리에 대한 책임 해당 함수를 호출한 영역으로 넘어간다.

 

그래서 부른 곳 func02에서 예외처리를 해주고 interface정의 한 곳에서 에러에 대한 처리를 따로 해주는 것이다.

 

이 스택풀기는 예외가 처리될 때까지 호출된 함수의 역순으로(거꾸로 올라가며) 예외인 데이터가 전달된다.

 

시스템 오류로 인해 발생한 예외가 아니라면 프로그램의 실행이 불가능한 예외상황이 아닐 경우 반드시 프로그래머가 예외상황을 처리해야 한다.

 

 

만약 자료형이 일치하지 않아도 예외데이터는 전달이 된다.

 

예를들어 throw 예외 데이터의 자료형과 catch의 매개변수가 다르다 하더라도 데이터는 전달된다.(처리는 되지않음)

 

또한 하나의 try블록과 다수의 catch블록이 발생할 수 있다.

	public void func02(T t) {
		System.out.println(1);
		try {
			t.func01();
		} catch (InterruptedException e) {

		}catch (Exception e) {
			// TODO: handle exception
		}
		System.out.println(2);
	}

요런너낌?

 

사이트의 정보

코딩하렴

으렴

활동하기