[211124] 교육 24일차

oxllz·2022년 2월 4일
0

교육

목록 보기
18/41

Thread : a light-weighted process
Process : a running program ( 동작하는 프로그램 )

  • Thread 는 Process 안에서만 존속할 수 있다
    모든 Thread 가 종료된 시점에서 Process 는 종료된다.

Program : executable file ( 실행 가능한 파일 )


스레드

public class Test203 {
	public static void main( String[] args ) {
		Runnable r = new Runnable(){
			public void run() {
				System.out.println("HelloThread");
			}
		};
		Thread t = new Thread( r );
		t.start();
	}
}

Thread 를 생성하는 방법

  1. Runnable 인터페이스를 상속받은 클래스의 인스턴스를 생성한다.
  2. public void run() 을 오버라이딩 한다.
  3. Thread 의 생성자에 넣어준다. ( Thread 생성 )
  4. start() 호출하면 > OS에 요청하여 Thread 를 할당받고 > 그것이 run() 을 돌린다
public class Test204 {
	public static void main( String[] args ) {
		StringBuffer sb = new StringBuffer();
		Runnable r = new Runnable(){
			public void run() {
				for( int i = 0 ; i < 100 ; i++ ) {
					try {
						Thread.sleep( 350 );
					}
					catch( InterruptedException e ) {}
					System.out.println("run " + i );
					sb.append('*');
				}
				System.out.println("run end " + sb.toString() );
			}
		};
		Thread t = new Thread( r );
		t.start();
        //
		for( int i = 0 ; i < 100 ; i++ ) {
			try {
				Thread.sleep( 250 );
			}
			catch( InterruptedException e ){}
			System.out.println("main " + i );
			sb.append('#');
		}
		System.out.println("main end");
	}
}
실행결과 >>
main 0
run 0
main 1
run 1
main 2
main 3
run 2
main 4
run 3
main 5
run 4
main 6
main 7
run 5
main 8
run 6
main 9
main 10

sleep( int t ) throws InterruptedException
Thread.sleep( 500 ); -- 0.5 초 동안 잠시 멈추어선다

스레드
하나의 프로세스 안에서 독자적으로 동작하는 가벼운 프로세스를 생성하는 것이 쓰레드의 개념이 된다.

쓰레드를 생성하고 돌리는 프로그램에서는 main 이 끝났다고 해서 끝난게 아니라 모든 쓰레드가 끝이 나야 프로그램은 종료된다.

하나의 프로세스 안에서 생성된 쓰레드들 사이에서는 메모리 공유가 가능하다.

  • 프로세스 ( 동작하는 프로그램 ) 상의 메모리 공유는 불가능하다.
// 스레드를 생성하고 이용하는 두번째 방법
class Kim extends Thread {
	public void run() {
		System.out.println("HelloWorld");		
	}
}
//
public class Test205 {
	public static void main( String[] args ) {
		Thread t = new Kim();
		t.start();
	}
}

Runnable 은 생각하지 않고 스레드를 상속받은 클래서에서 run() 을 오버라이딩 해준다. start() 를 호출하면 OS 로 부터 스레드가 할당되어 run() 을 동작시킨다.

스레드는 물리적인 CPU 를 소프트웨어적으로 분산을 만드는 개념과 같다. 이들은 독자적, 독립적으로 구동되며( 동시 실행가능), 메모리를 공유한다.

3개로 나누면 1/3 으로 힘이 분산되는데 왜 사용하는걸까??
어떤 하나가 서비스를 길게 받는 일이 생긴다면 다른 것들은 우회할 수 있어야 한다. 서비스를 제공하는 서버 프로그램 에서는 스레드 개념이 필수적이다.


synchronized

class Toilet {
	public void bigWork( String by ) {
		System.out.println("BW STEP 1 : " + by );
		System.out.println("BW STEP 2 : " + by );
		System.out.println("BW STEP 3 : " + by );
		System.out.println("BW STEP 4 : " + by );
		System.out.println("BW STEP 5 : " + by );
	}	
}
class Kim extends Thread {
	private Toilet toi = null;
	public Kim( Toilet t ) { this.toi = t; }
	public void run() {	
		for( int i = 0 ; i < 10 ; i++ ) {
			toi.bigWork("kim");
		}
	}
}
class Park extends Thread {
	private Toilet toi = null;
	public Park( Toilet t ) { this.toi = t; }	
	public void run() { 
		for( int i = 0 ; i < 10 ; i++ ) {
			toi.bigWork("park");
		}
	}
}
public class Test206 {
	public static void main( String[] args ) {
		Toilet toilet = new Toilet();
		Thread k = new Kim( toilet );
		Thread p = new Park( toilet );
		k.start();
		p.start();
	}
}
살행결과>>
BW STEP 1 : Kim
BW STEP 1 : Park
BW STEP 2 : Park
BW STEP 3 : Park
BW STEP 4 : Park
BW STEP 5 : Park
BW STEP 1 : Park
BW STEP 2 : Park
BW STEP 3 : Park
BW STEP 4 : Park
BW STEP 5 : Park

스레드의 문제

여러 스레드가 동시에 하나의 인스턴스를 사용하는 경우에 같은 칸에서 동작하는 일이 발생!

위의 코드를 예로 들자면 화장실 칸이 5개가 있다. 그런데 Kim 과 Park 이 같은 화장실 칸에 들어가서 동시에 일을 보겠다고 하는 상황과 같다.

해결 방법 : 모두가 각각 자신의 전용 화장실을 가지고 있으면 이런 일이 안 생기지만 현실적으로는 불가능하다. 따라서 이런 경우에는 먼저 사용하는 쓰레드가 문을 잠그고 들어가면 그 다음 쓰레드는 기다리도록 한다. ( 동기화 개념 )

class Kim extends Thread {
	private Toilet toi = null;
	public Kim( Toilet t ) { this.toi = t; }
	public void run() {	
		for( int i = 0 ; i < 10 ; i++ ) {
			synchronized( toi ) {
				toi.bigWork("kim");
			}
		}
	}
}
class Park extends Thread {
	private Toilet toi = null;
	public Park( Toilet t ) { this.toi = t; }	
	public void run() { 
		for( int i = 0 ; i < 10 ; i++ ) {
			synchronized( toi ) {
				toi.bigWork("park");
			}
		}
	}
}
실행결과>>
BW STEP 1 : Kim
BW STEP 2 : Kim
BW STEP 3 : Kim
BW STEP 4 : Kim
BW STEP 5 : Kim
BW STEP 1 : Park
BW STEP 2 : Park
BW STEP 3 : Park
BW STEP 4 : Park
BW STEP 5 : Park

synchronized( toi ) {
		....
}

{ ... } 의 영역에 들어가기 위해선 toi 가 가리키는 인스턴스가 가진 key 를 획득해야 한다. 모든 인스턴스는 하나의 키를 가지고 있다.

Kim 과 Park 이 toilet 에 거의 동시에 들어왔어도 Kim 이 먼저 열쇠를 갖고 들어가면 Park 은 열쇠가 반납될 때 까지 기다려야 한다.

열쇠를 가져야만 { 을 통과할 수 있고 , } 시점에서 열쇠는 인스턴스에게 반납된다.

synchronized 를 통해서 동시에 인스턴스를 이용하는 스레드에 의해서 벌어질 수 있는 상황 ( 하나의 객체를 여러 쓰레드가 동시에 이용하면 안되는 일 ) 을 막을 수 있다.

0개의 댓글