본문 바로가기

Back/Java

[JAVA/멀티스레드] JAVA멀티스레딩 - 스레드생성2부. 스레드 상속 (도둑과 경찰 예제)

스레드 생성방법 두번째

스레드에 대한 개별적인 객체와 Runnable의 또다른 객체를 만드는 대신 (스레드생성1부에서 했던 방법),

스레드를 확장하는 새 클래스를 만든다.

Thread 클래스를 열어서 확인해보면 Runnable인터페이스가 구현된 것임을 알수 있다.

 

현재 스레드와 직접적으로 관련된 많은 데이터와 메서드에 엑세스 할 수 있어요

package thread.creation.example;
 
public class Main {
	public static void main(String[] args) {
            Thread thread = new NewThread();
            thread.start();
	}
    public static class NewThread extends Thread{
    	@Override
        public void run() {
            this.getName();
        }
    }
}

 

상속 계층 생성

스레드 클래스 확장기능으로

심층적인 객체지향 프로그래밍과 상속계층을 생성할 수 있고,

스레드 그룹의 공통적인 기능을 캡슐화 할 수 있다.

 

 

Case Study (도둑과 경찰)

 상속 계층을 사용해서 구현

  • 배경
    • 돈을 보관할 안전한 금고 설계
    • 해커들이 코드를 추측해서 금고를 여는데 얼마나 걸리는지 궁금
  • 구현
  • 해커 스레드 : 금고의 코드를 깨려하는 기능. 여러개 구현
  • 경찰 스레드 : 10초안에 해커를 잡으러 옴. 10초를 세는 동안 경찰스레드는 도착상황을 화면에 띄워 보여줌.

금고 객체

스레드가 아닌 일반 객체

비밀번호를 가지고 있고,

비밀번호가 맞는지 확인하는 메서드를 가짐

public static class Vault {
   private int password;

   public Vault(int password) {
      this.password = password;
   }

   private boolean isCorrectPassword(int guess) {
      try {
         // 해커의 속도를 늦추기 위해
         Thread.sleep(5);
      } catch (InterruptedException e) {
      }
      return this.password == guess;
   }
}

 

해커 스레드

// 일반적인 해커 클래스. 스레드를 확장해서 생성.
// 금고 필드는 protected 처리 & 생성자를 통해 전달.
private static abstract class HackerThread extends Thread {
   protected Vault vault;

   public HackerThread(Vault vault) {
      this.vault = vault;
      // 클래스명을 스레드명으로 사용한다.
      this.setName(this.getClass().getSimpleName());
      // 우선순위는 최대값이다.
      this.setPriority(Thread.MAX_PRIORITY);
   }

   @Override
   public void start() {
      System.out.println("Starting thread : " + this.getName());
      super.start();
   }
}
// 비밀번호를 아래부터 순서대로 올라가는 해커
private static class AscendingHackerThread extends HackerThread {
   public AscendingHackerThread(Vault vault) {
      super(vault);
   }

   @Override
   public void run() {
      for (int guess = 0; guess < MAX_PASSWORD; guess++) {
         System.out.println(this.getName() + "guessed the password " + guess);
         System.exit(0);
      }
   }
}
// 비밀번호를 위에서 순서대로 내려가는 해커
private static class DescendingHackerThread extends HackerThread {
   public DescendingHackerThread(Vault vault) {
      super(vault);
   }

   @Override
   public void run() {
      for (int guess = MAX_PASSWORD; guess >= 0; guess--) {
         System.out.println(this.getName() + "guessed the password " + guess);
         System.exit(0);
      }
   }
}

 

메인 메서드 (스레드 실행)

public static final int MAX_PASSWORD = 9999;

public static void main(String[] args) {
   // 실행할때마다 임의의 비밀번호를 생성
   Random random = new Random();
   Vault vault = new Vault(random.nextInt(MAX_PASSWORD));

   List<Thread> threads = new ArrayList<>();
   threads.add(new AscendingHackerThread(vault));
   threads.add(new DescendingHackerThread(vault));
   threads.add(new PoliceThread());

   // 모두 Thread를 상속받았기 때문에, 구체적인 타입에 상관없이 Thread로 취급해도된다. (다형성)
   for (Thread thread : threads) {
      thread.start();
   }
}