본문 바로가기

JAVA

java #13 쓰레드 총 정리 1 (싱글쓰레드, 멀티쓰레드, main쓰레드)

1.쓰레드
1)프로세스와 쓰레드
a. 프로세스: 실행중인 프로그램, 자원(= 메모리, CPU)과 쓰레드로 구성
b. 쓰레드 : 프로세스 내에서 실제 작업을 수행, 모든 프로세스는 최소한 하나의 쓰레드를 가지고 있다.
c. 싱글 쓰레드 프로세스 = 자원 + 쓰레드 , 멀티 쓰레드 프로세스 : 자원 + 쓰레드 + 쓰레드 + ... + 쓰레드
d. 하나의 새로운 프로세스를 생성하는 것보다 하나의 새로운 쓰레드를 생성하는 것이 더 적은 비용이 든다.
ex) CGI(씽글 쓰레드 프로세스) vs Java Servlet(멀티 쓰레드 지원 -> 효율적)

2)멀티쓰레드의 장단점
a. 장점
- 시스템 자원을 보다 효율적으로 사용할 수 있다.
- 사용자에 대한 응답성이 향상된다. ex) 메신저로 파일을 전송했을 때 전송중임에도 불구하고 채팅을 보낼 수 있다.
- 작업이 분리되어 코드가 간결해진다.

b. 단점
- 동기화에 주의해야 한다.
- 교착상태(= 서로 필요한 자원을 사용중이라 줄 때까지 대치하고 있는 것)가 발생하지 않도록 주의해야 한다.
- 각 쓰레드가 효율적으로 고르게 실행될 수 있게 해야 한다. ex) 기아 (쓰레드가 사용되지 않음)

3) 쓰레드의 구현과 실행
a. Thread클래스를 상속

ex) class MyThread extends Thread {
	public void run() { // 쓰레드클래스의 run()을 오버라이딩
} } 

b. Runnable 인터페이스를 구현
ex) class MyThread2 implements Runnable {
	public void run() { // Runnable 인터페이스의 추상메소드 run()을 구현
} }

ex)class ThreadEx1 {
	public static void main(String args[]) {
		ThreadEx1_1 t1 = new ThreadEx1_1();

		Runnable r  = new ThreadEx1_2();
		Thread   t2 = new Thread(r);	  // 생성자 Thread(Runnable target)

		t1.start();
		t2.start();
	}
}

class ThreadEx1_1 extends Thread {
	public void run() { // 쓰레드가 수행할 작업을 작성
		for(int i=0; i < 500; i++) {
			System.out.println(0); // 조상인 Thread의 getName()을 호출
		}
	}
}

class ThreadEx1_2 implements Runnable { 
	public void run() { // 쓰레드가 수행할 작업을 작성
		for(int i=0; i < 500; i++) {
			// Thread.currentThread() - 현재 실행중인 Thread를 반환한다.
		    System.out.println(1);
		}
	}
}


4) 쓰레드의 실행 - start()
a. 쓰레드를 생성한 후에 start()를 호출해야 쓰레드가 작업을 시작한다.
ex) t1.start(); // 쓰레드 t1을 실행시킨다. -> 쓰레드를 실행시킨다고 해서 즉시 실행되는 것이 아니라
     t2.start(); // 쓰레드 t2을 실행시킨다.     OS 스케쥴러가 실행순서 결정

b. start()와 run() : 클래스를 만들어 run()을 실행해야 스택이 생겨서 멀티스레드가 가능하다. 메인에 run()을 사용시 단일 쓰레드가 됨.

5) main 쓰레드
a. main메서드의 코드를 수행하는 쓰레드
b. 쓰레드는 '사용자 쓰레드'와 '데몬 쓰레드(= 보조 쓰레드)' 두 종류가 있다.
c. 실행 중인 사용자 쓰레드가 하나도 없을 때 프로그램은 종료된다. (메인 쓰레드가 죽어도 보조쓰레드가 살아있으면 프로그램은 종료되지 않음)

 class ThreadEx11 {
	static long startTime = 0;

	public static void main(String args[]) {
		ThreadEx11_1 th1 = new ThreadEx11_1();
		th1.start();
		startTime = System.currentTimeMillis();

		for(int i=0; i < 300; i++) {
			System.out.print("-");
		}

		System.out.print("소요시간: " + (System.currentTimeMillis() - ThreadEx11.startTime));
	}
}

class ThreadEx11_1 extends Thread {
	public void run() {
		for(int i=0; i < 300; i++) {
			System.out.print("|");
		}

		//System.out.print("소요시간2:" + (System.currentTimeMillis() - ThreadEx11.startTime));
	}
}


6) 싱글쓰레드와 멀티쓰레드 : 문맥전환이 여러 번인 멀티쓰레드가 수행시간이 조금 더 걸림.

7) 쓰레드의 I/O(입출력)블락킹(blobking)
a. 싱글쓰레드 -> 사용자로부터 입력을 기다리는 구간, 아무 일도 하지 않음!

import javax.swing.JOptionPane;

class ThreadEx6 {
	public static void main(String[] args) throws Exception
	{
		String input = JOptionPane.showInputDialog("아무 값이나 입력하세요."); 
		System.out.println("입력하신 값은 " + input + "입니다.");

		for(int i=10; i > 0; i--) {
			System.out.println(i);
			try {
				Thread.sleep(1000);
			} catch(Exception e ) {}
		}
	}
}

b. 멀티쓰레드 -> 사용자로부터 입력을 기다리는 구간, th2가 수행된다. => 효율적임

import javax.swing.JOptionPane;

class ThreadEx7 {
	public static void main(String[] args) throws Exception 	{
		ThreadEx7_1 th1 = new ThreadEx7_1();
		th1.start();

		String input = JOptionPane.showInputDialog("아무 값이나 입력하세요."); 
		System.out.println("입력하신 값은 " + input + "입니다.");
	}
}

class ThreadEx7_1 extends Thread {
	public void run() {
		for(int i=10; i > 0; i--) {
			System.out.println(i);
			try {
				sleep(1000);
			} catch(Exception e ) {}
		}
	}
}

8) 쓰레드의 우선순위(priority of thread)
a. 작업의 중요도에 따라 쓰레드의 우선순위를 다르게 하여 특정 쓰레드가 더 많은 작업시간을 갖게 할 수 있다.

ex) void setPriority(int newPriority) // 쓰레드의 우선산위를 지정한 값으로 변경한다.
     int getPriority()
     public static final int MAX_PRIORITY = 10 // 최대 우선순위
     public static final int MAX_PRIORITY = 1 // 최소 우선순위
     public static final int MAX_PRIORITY = 5 // 보통 우선순위