#4 Thread

지우·2026년 1월 4일

java2

목록 보기
5/13

1. 쓰레드와 멀티쓰레드

이것들은 기억하기

  • 자바에서 다중 상속이 불가능한 것을 감안하면 Runnable 인터페이스를 사용하는 것이 좋음
  • run( ) 메소드가 종료하면 쓰레드 종료
  • 한번 종료한 쓰레드는 다시 시작 X -> 다시 쓰레드 생성하고 start( ) 호출
  • 작업 쓰레드 이름 : thread.getName( );
  • 작업 쓰레드 이름 변경 : thread.setName( );

Lab#1 : 쓰레드의 생성과 실행

방법 1) Thread 클래스를 상속

class MyThread extends Thread {
	public void run() { //run() 메소드 오버라이딩
    	this.work();
    }
    public void work() {
    	for (int i=o; i<100; i++){
        	System.out.println("Thread로 만든 " + i);
            try {
				Thread.sleep(500);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} 
    

방법 2) Runnable 인터페이스 사용

class MyRunnable implements Runnable {
	public void run() {
    	this.work()
    }
    public void work() {
    	for (int i=0; i<100; i++){
        	System.out.println("Runnable로 만든 " + i);
            try {
				Thread.sleep(200);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} 
    	

방법 3) 익명 클래스 사용

Thread t3 = new Thread(
				new Runnable() {
                	public void run() {
                    	System.out.println("익명 클래스로 만든 " + i);
                    }
               }
           );
t3.start();

방법 4) 람다식 사용

Thread t4 = new Thread(()->{
	System.out.println("람다식으로 만든 " + i);
    });
t4.start();

람다식 : 불필요한 선언 지우고 핵심 로직만 남기기
( ) : 매개변수 없음 -> { } : 중괄호 안의 내용 실행
Runnable() -> run() 메소드 하나라서 생략 가능

Lab#2 : 멀티쓰레드 동작 - Horse

Lab#3 : 짱구맹구흰둥이

//Thread 상속받은 Player1

//Runnable로 구현된 Player2

Player1에 의해 생성된 p1, p2, p3과 Player2에 의해 생성된 t1, t2, t3의 속도
=> 출력할 때마다 순서 달라짐!! start( )가 호출된 순서대로 출력되지 않음

Lab#4 : 자동차 경주

안전성 문제로 stop( )은 사용 안함!! -> 대신 break, return, interrupt( ) 신호 사용

main에서 car2에 interrupt 신호 보냄 -> 스포츠카: interrupt 발생

goal을 설정한 후 goal까지 달리기, 중간에 interrupt 신호 감지하면 쓰레드 종료

++
랜덤하게 설정한 내용과 interrupt 신호 감지에 대한 내용을 잘 이해할 수 있어야할듯,,,,,

Lab#5 : MyBank

synchronized : 메소드 전체 혹은 코드 블록에 지정하여 한번에 하나의 쓰레드만이 공유 데이터에 접근할 수 있도록 제어

기존의 lab#5의 User을 수정하여 두 명의 user을 설정하여 한 명은 desposit만, 한 명은 withdraw만 실행하도록 함

Lab#6 : Family Account

이건 위에서 내가 수정한 내용과 동일!

deposit과 withdraw 모두 동기화처리해서
한 계좌에 여러 쓰레드가 동시에 호출할 수는 있지만 처리는 한번에 하나씩 되도록 함 -> 하나의 쓰레드가 공유 데이터를 사용하면 다른 쓰레드는 사용하지 못하게 함

join( ) : 다른 쓰레드 실행 대기

?? // throws InterruptedException 이거 이해 필요함,,,,,,

Lab#7 : 아기돼지삼형제

join( ) 사용해서 모든 쓰레드가 완료될 때까지 대기

안전한 공유를 위한 Thread 상태 제어

join( ), wait( ), notify( ) ... 동기화처리 필요

sleep( ) : 일정 시간동안 쓰레드 일시정지

  • Thread 클래스 소속
  • lock을 유지한 채 지정 시간이 지나면 자동 재개

wait( ) : 다른 쓰레드의 신호를 기다리며 일시중지

  • 누군가 깨워줄 때까지 잠자기
  • Object 클래스 소속
  • lock을 반납한 채, 누군가 notify( ) 해줄 때까지 기다림

Lab#8 : 잠자는 숲속의 공주

Prince와 Princess 클래스에서 각각 lock 변수 선언
synchronized(lock)을 통해 동기화
wait( )와 notify( )는 synchronized(lock) 블록 안에 있어야 함 -> lock을 가지고 있는 동안에만 실행!

Princess )
1. synchronized(lock)
2. lock.wait( ) -> 열쇠 놓고 쓰레드 정지

Prince )
1. synchronized(lock) : princess가 놓은 열쇠 잡음
2. lock.notify( ) -> princess 깨움

Lab#10 : 생산자/소비자 문제

synchronized가 get( )과 put( ) 메소드 자체에 붙어 있음
-> Buffer 객체 자체가 lock의 역할을 함

empty가 true라면 wait( )를 호출하고 잠듬 -> notifyAll( ) 신호를 받고 깨어났을 때, 순간적으로 다른 쓰레드가 먼저 채가서 다시 상태가 변했을 수도 있음 -> 조건 재확인!!

notifyAll( ) -> 모든 생산자와 소비자를 깨우며 조건을 다시 확인하고, 프로그램이 계속 실행되도록 함

Buffer은 wait( )로 쓰레드를 멈추게 하고, notifyAll( )로 다시 깨우면서
생산자와 소비자가 서로 박자를 맞추게 유도 => 케이크가 없는데 소비하려고 하거나 있는데 또 생산하려고 하는 일들을 막을 수 있음






++ 동기화와 구체적인 상태 제어 더 잘 쓸 수 있도록,,

0개의 댓글