1 교시
Task: 일 또는 작업이라는 말로 번역하며 프로세스와 Thread를 포함한 개념
Process: 운영체제로부터 자원을 할당받아서 동작하는 독립된 프로그램으로 하나의 프로세스 가 다른 프로세스에 영향을 미치지 않음
Thread: 프로세스 내의 명령어 블록으로 시작점과 종료점을 가지는 일련된 하나의 작업 흐름으로 혼자서 동작할 수 없고 항상 Process 내에 속해서 동작해야 함
순차적으로 동작하는 문장들의 단일 집합으로 다른 Thread와 자원을 공유할 수 있으며 실행 중 에 멈출 수 있으며(제어권을 다른 Thread에게 넘김) 다른 Thread를 수행하는 것이 가능
프로세스는 제어권을 가지면 종료 될 때까지 제어권의 이동이 불가능하고 다른 프로세스와 자 원을 공유하지 않으며 통신을 이용해서만 다른 프로세스와 자원을 공유할 수 있음
java 에서는 java.lang 패키지에서 Thread를 위한 Runnable 인터페이스와 Thread, ThreadGroup, ThreadLocal, InheritableThreadLocal 클래스를 제공
1.5 이상의 버전에서는 Thread의 동기화를 위해서 java.util.concurrent 패키지 제공
1.메인(main) 스레드
1) 모든 자바 프로그램은 메인 스레드가 main() 메소드를 실행해서 시작
2) main() 메소드의 첫 코드부터 아래로 순차적으로 실행
3) 실행 종료 조건 l 마지막 코드 실행 l return 문을 만나면
2. main 스레드는 작업 스레드들을 만들어 병렬로 코드들 실행
3. 멀티 스레드를 이용해 멀티 태스킹 수행
4. 프로세스의 종료
1) 싱글 스레드: 메인 스레드가 종료하면 프로세스도 종료
2) 멀티 스레드: 실행 중인 스레드가 하나라도 있다면 프로세스 미종료
5. 스레드 프로그래밍의 장점
=> CPU의 사용률을 향상시킴
=> 자원을 보다 효율적으로 사용
=> 사용자에 대한 응답성이 향상
=> 작업이 분리되어 코드가 간결
6. 스레드 프로그래밍의 단점
=> 동기화나 교착상태 등을 고려해야 하기 때문에 프로그램이 어려워짐
=> 너무 많은 스레드를 생성하면 스레싱 현상이 발생해서 성능이 저하 될 가능성이 있음
2 교시
** Thread
=> 프로세스 내에 만드는 것으로 작업 도중 다른 작업으로 제어권을 넘길 수 있도록 해주는 작업 단위
=> 단독으로는 실행할 수 없고 프로세스 (Method) 내에서 생성해서 실행
=> 일반 메소드 호출은 하나의 메소드의 수행이 완료될 때까지 다른 메소드의 수행을 할 수 없는 구조이다
이런 방식을 동기식(Synchronized)이라고 한다.
=> 스레드는 하나의 작업이 진행 중인 동안에도 제어권을 다른 스레드로 옮겨서 처리가 가능하다.
이런 방식을 비동기식(Asynchronized)이라고 한다.
=> 스레드를 만드는 방식은 거의 대다수 프로그래밍 언어가 비슷하고 해결해야 할 문제들도 비슷하다.
1. 생성
1) java.lang.Thread 클래스 이용
=> Thread 클래스로부터 상속받는 클래스를 만들어서 run 메소드를 구현
=> 클래스의 인스턴스를 생성해서 start() 를 호출
=> Thread 클래스에는 run 메소드 이외의 여러 메소드가 존재
2) java.lang.Runnable 인터페이스를 이용
=> Runnable 인터페이스를 구현한 클래스를 만들어서 run 메소드를 구현
=> 클래스의 인스턴스를 생성
=> Thread 클래스의 인스턴스를 생성할 때 생성자의 매개변수로 만들어진 인스턴스를 대입
=> Thread 클래스의 인스턴스가 run을 호출
=> Runnable 인터페이스에는 run 메소드만 존재
2. Java에서 상속이나 구현하는 방법
1) 상속이나 구현한 클래스를 만들고 인스턴스를 생성
2) 클래스를 만들지 않고 상속이나 구현한 인스턴스를 생성 - anonymous class
package thread1; public class ThreadMain { public static void main(String[] args) { ThreadEx th1 = new ThreadEx(); ThreadEx th2 = new ThreadEx(); //일반 프로세스 형태로 호출 th1.run(); th2.run(); } } |
package thread1; public class ThreadMain { public static void main(String[] args) { ThreadEx th1 = new ThreadEx(); ThreadEx th2 = new ThreadEx(); //일반 프로세스 형태로 호출 //th1.run(); //th2.run(); // 스레드로 실행 th1.start(); th2.start(); } } |
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 |
0 0 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 |
3 교시
스레드 만들기
4 교시
외부입출력 장치와 작업이 이루어지면 스레드를 작성하지 않아도 디폴트로 스레드를 수행한다.
3. Daemon Thread
=> Daemon Thread가 아닌 스레드가 없으면 자동으로 종료되는 스레드
=> 백그라운드에서 작업하고 있다가 다른 스레드가 종료되면 같이 종료되는 스레드
=> 주기적으로 계속해서 해야하는 작업 중에서 자동으로 종료되면 좋을 것 같은 작업을 만들 때 사용 : 응용프로그램에서 주기적으로 자동 저장 기능이나 서버와 클라이언트 시스템에서 데이터 백업 등에서 주로 이용
=> start 를 호출하기 전에 setDaemon(true)를 호출하면 된다.
4. Thread Priority (우선 순위)
=> 스레드의 우선 순위 설정 가능
=> 우선 순위를 설정하면 스레드의 시작 순서나 동작 횟수를 서로 다르게 설정할 수 잇다.
=> getPriority 메소드를 이용해서 우선 순위를 정수로 리턴받을 수 있고 setPrioruty로 우선순위를 설정할 수 있다.
=> 우선 순위가 높다고 해서 반드시 먼저 수행하거나 자주 수행되는 것은 아니다.
=> 우선 순위를 설정할 때 매개변수는 정수인데 정수를 직접 설정하는 것은 바람직하지 않다.
Thread클래스의 Field를 이용하는 것을 권장한다.
Thread.MAX_PRIORITY, Thread.NORMAL_PRIORITY, Thread.MIN_PRIORUTY 등으로 설정
=> MS Windows는 스레드의 우선 순위가 1부터 10까지 이지만 리눅스는 1부터 7까지 이다.
10 이라고 직접 설정하면 리눅스에서는 적용이 안된다.
Thread.MAX_PRIORITY로 설정하면 원도우에서는 10, 리눅스에서는 7로 설정된다.
5. ThreadGroup
=> 여러개의 스레드를 무껑주기 위해서 제공하는 클래스
=> 리눅스에서 제대로 동작하지 않는 경우가 있어서 실제 사용은 잘 하지 않는다.
=> List를 이용해서 직접 묶어서 사용한다.
5 교시
6. 스레드의 강제 종료
1) Interrupt : 다른 작업을 방해하는 것
=> 작업 별로 우선순위라는 것이 있어서 우선순위가 높은 작업이 발생시킨 인터럽트만 전달된다.
2) 강제 종료
=> 스레드의 실행 구문에서 InterruptedException이 발생하면 return하도록 코드를 작성
=> 스레드 인스턴스가 interrupt() 라는 메소드를 호출하도록 하면 된다.
3) 되도록이면 스레드를 만들 때 InterruptedException이 발생하면 종료하도록 작성하는 것이 좋다.
스마트폰의 경우는 InterruptedException이 발생하면 현재 상태를 저장해두었다가 해결이 되면 이어서 하도록 적성하는 것이 좋다.
6 교시
7. Mutual Exclusion (상호 배제)
=> 하나의 스레드가 수정하고 있는 자원을 사용을 끝내기 전에 다른 스레드가 수정할 수 없도록 하는 것
=> Critical Section(임계영역) : 공유자원을 사용하는 코드 영역
1) synchronized method
=> 메소드의 결과형 앞에 synchronized 를 붙여주면 이 메소드는 수행하고 있는 도중에 다른 스레드에게 제어권을 넘기지 않는다.
메소드를 synchronized화 하면 공유도가 떨어진다.
2) synchronize block
=> 공유 자원을 한 번에 사용해야 하는 코드 영역을 synchronized(공유객체){ } 로 묶어주는 것
{ } 안의 코드 영역을 실행할 때는 다른 스레드가 공유객체를 사용할 수 없도록 한다.
3) ReentrantLock 을 이용
=> 인스턴스를 만들고 lock()을 호출하면 동기화 블럭이 되고 unlock()을 호출하면 해제
8 교시
8. 생산자와 소비자 문제
=> 생산자 스레드는 자원을 생산하고 소비자 스레드는 자원을 소비하는 경우 동시에 수행할 수 있도록 만들 수 있는데 이 경우에는 생산자 스레드가 자원을 생산하지 않은 상태에서 소비자 스레드가 자원을 소비할려고 하면 예외가 발생해서 소비자 스레드가 종료되버리는 현상이 발생할 수 있다.
=> 공유자원이 없을 때는 소비자 스레드가 중지 상태에 있다가 생산자가 자원을 생성하고 신호를 주면 작업을 수행하도록 하면 된다.
=> 작업을 대기하는 것은 wait 메소드를 호출하면 되고 신호를 보내는 것은 notify() 와 notifyAll()을 이용한다.
notify()는 wait 중인 스레드 중에서 하나를 실행시키는 것이고 notifyAll()은 wait 중인 모든 스레드를 실행시키는 것이다.
=> wait메소드와 notify 메소드는 synchronize 메소드에서만 사용이 가능하다.
9. Semaphore
=> 동시에 수행할 스레드의 개수를 설정할 수 있는 클래스
=> ThreadPool : 여러 개의 스레드를 미리 만들어두고 빌려서 사용할 수 있도록 해주는 스레드의 집합
=> ThreadPool은 데이터베이스나 서버에서 많이 사용하는데 Semaphore를 이용해서 구현 가능
연습문제
{20, 19, 76, 87, 22} : 거리가 가장 가까운 2개의 숫자 조합을 찾아내서 출력
'Java' 카테고리의 다른 글
19일차 공부 Network, Socket (0) | 2020.05.04 |
---|---|
18일차 공부 IO, Serializable (0) | 2020.05.01 |
16일차 공부 Set, Map, 배열의 배열, Random, 프라임넘버 개수구하기 (0) | 2020.04.28 |
15일차 공부Collection, ArrayList, LinkedList, Stack (0) | 2020.04.27 |
14일차 공부 String, 서식, StringBuilder, Generic, Array, Bubble sort, 정렬 (0) | 2020.04.24 |