9) 쓰레드 그룹
a. 서로 관련된 쓰레드를 그룹으로 묶어서 다루기 위한 것
b. 모든 쓰레드는 반드시 하나의 쓰레드 그룹에 포함되어 있어야 한다.
c. 쓰레드 그룹을 지정하지 않고 생성한 쓰레드는 'main쓰레드 그룹'에 속한다.
d. 자신을 생성한 쓰레드(부모 쓰레드)의 구릅과 우선순위를 상속받는다.
ex) Thread(Theadgroup, String name)
Thread(Theadgroup, Runnable target)
10) 데몬 쓰레드(deamon thread)
a, 일반 쓰레드의 작업을 돕는 보조적인 역할을 수행
b. 일반 쓰레드가 모두 종료되면 자동적으로 종료된다.
c. 가비지 컬렉터, 자동저장, 화면 자동갱신 등에 사용된다.
d. 무한루프와 조건문을 이용해서 실행 후 대기하다가 특정조건이 만족되면 작업을 수행하고 다시 대기하도록 작성한다.
ex) boolean isDeamon() - 쓰레드가 데몬 쓰레드인지 확인한다. 데몬 쓰레드이면 true를 반환
void setDeamon(boolean on) - 쓰레드를 데몬 쓰레드로 또는 사용자 쓰레드로 변경, 매개변수 on을 true로 지정하면 데몬 쓰레드가 된다. -> 반드시 start()를 호출하기 전에 실행되어야 한다. 그렇지 않으면 IllegalTheadStateException이 발생한다.
class ThreadEx10 implements Runnable {
static boolean autoSave = false;
public static void main(String[] args) {
Thread t = new Thread(new ThreadEx10()); // Thread(Runnable r)
t.setDaemon(true); // 이 부분이 없으면 종료되지 않는다.
t.start();
for(int i=1; i <= 10; i++) {
try{
Thread.sleep(1000);
} catch(InterruptedException e) {}
System.out.println(i);
if(i==5)
autoSave = true;
}
System.out.println("프로그램을 종료합니다.");
}
public void run() { // 데몬쓰레드 - 자동종료(일반 쓰레드가 없을 때)
while(true) {
try {
Thread.sleep(3 * 1000); // 3초마다
} catch(InterruptedException e) {}
// autoSave의 값이 true이면 autoSave()를 호출한다.
if(autoSave) {
autoSave();
}
}
}
public void autoSave() {
System.out.println("작업파일이 자동저장되었습니다.");
}
}
11) 쓰레드의 상태
a. new : 쓰레드가 생성되고 아직 start()가 호출되지 않는 상태
b. RUNNABLE : 실행 중 또는 실행 가능한 상태
c. BLOCKED : 동기화블럭에 의해서 일시정지된 상태(lock이 풀릴 때까지 기다리는 상태)
d. WAITING, TIMED_WAITING : 쓰레드의 작업이 종료되지는 않았지만 실행가능하지 않은 일시정지 상태
e. TERMINATED : 쓰레드의 작업이 종료된 상태
12) 쓰레드의 실행제어 :쓰레드의 실행을 제어할 수 있는 메서드가 제공된다.
a. sleep()
- 현재 쓰레드를 지정된 시간동안 멈추게 한다.
ex) static void sleep(long millis) // 천분의 일초 단위
- 예외 처리를 해야 한다. (InterruptedException이 발생하면 깨어남)
ex)
try {
Thread.sleep(1,500000); // 쓰레드를 0.0015초동안 멈추게 한다.
} catch(InterruptedException e) {} // 필수 예외 처리
void delay(long millis) {
try {
Thread.sleep (millis) // 메소드를 만들어서 한 줄로 사용 ex) delay(15);
} catch(InterruptedException e) {}
- 특정 쓰레드를 지정해서 멈추게 하는 것은 불가능하다. (자기 자신만 적용)
ex)
try {
Thread.sleep(2000); // 클래스이름을 사용해야 안 헷갈림!
} catch(interruptedException e) {}
class ThreadEx12 {
public static void main(String args[]) {
ThreadEx12_1 th1 = new ThreadEx12_1();
ThreadEx12_2 th2 = new ThreadEx12_2();
th1.start();
th2.start();
try {
th1.sleep(2000); // th1을 잠자게 하는 것이 아니라 메인 쓰레드가 잠자는 것!
} catch(InterruptedException e) {}
System.out.print("<<main 종료>>");
} // main
}
class ThreadEx12_1 extends Thread {
public void run() {
for(int i=0; i < 300; i++) {
System.out.print("-");
}
System.out.print("<<th1 종료>>");
} // run()
}
class ThreadEx12_2 extends Thread {
public void run() {
for(int i=0; i < 300; i++) {
System.out.print("|");
}
System.out.print("<<th2 종료>>");
} // run()
}
b. interrupt()
- 대기상태인 쓰레드를 실행대기 상태로 만든다.
void interrup() : 쓰레드의 interrupted상태를 false에서 true로 변경.
boolean isInterrupted() : 쓰레드의 interrupted상태를 반환.
static boolean interrupted() : 현재 쓰레드의 interrupted상태를 알려주고, false로 초기화
import javax.swing.JOptionPane;
class ThreadEx13_1 {
public static void main(String[] args) throws Exception {
ThreadEx13_2 th1 = new ThreadEx13_2();
th1.start();
System.out.println("isInterrupted():"+ th1.isInterrupted()); // false인거 보기!
String input = JOptionPane.showInputDialog("아무 값이나 입력하세요.");
System.out.println("입력하신 값은 " + input + "입니다.");
th1.interrupt(); // interrupt()를 호출하면, interrupted상태가 true가 된다.
System.out.println("isInterrupted():"+ th1.isInterrupted()); // true -> 카운트 종료
}
}
class ThreadEx13_2 extends Thread {
public void run() {
int i = 10;
while(i!=0 && !isInterrupted()) {
System.out.println(i--);
for(long x=0;x<2500000000L;x++); // 시간 지연
}
System.out.println("카운트가 종료되었습니다.");
} // main
}
c. suspend() : 쓰래드를 일시정지 시킴, 사용하지 않을 것을 권장!
d. resume() : suspend()에 의해 정지된 쓰레드를 실행대기상태로 만듬, 사용하지 않을 것을 권장!
e. stop() : 쓰레드를 즉시 종료시킴, 사용하지 않을 것을 권장!
f. join()
- 지정된 시간동안 특정 쓰레드가 작업하는 것을 기다린다
void join() // 작업이 모두 끝날 때까지
void join(long millis) // 천분의 일초 동안
- 예외 처리를 해야 한다(InterruptedException이 발생하면 작업 재개)
class ThreadEx19 {
static long startTime = 0;
public static void main(String args[]) {
ThreadEx19_1 th1 = new ThreadEx19_1();
ThreadEx19_2 th2 = new ThreadEx19_2();
th1.start();
th2.start();
startTime = System.currentTimeMillis(); // 시작 시간
try {
th1.join(); // main쓰레드가 th1의 작업이 끝날 때까지 기다린다.
th2.join(); // main쓰레드가 th2의 작업이 끝날 때까지 기다린다.
} catch(InterruptedException e) {}
System.out.print("소요시간:" + (System.currentTimeMillis() - ThreadEx19.startTime));
} // main
}
class ThreadEx19_1 extends Thread {
public void run() {
for(int i=0; i < 300; i++) {
System.out.print(new String("-"));
}
} // run()
}
class ThreadEx19_2 extends Thread {
public void run() {
for(int i=0; i < 300; i++) {
System.out.print(new String("|"));
}
} // run()
}
for(int i = 0; i < 20; i++) {
repuireedMemory = (int)(Math.random() * 10) *20;
if(gc.freeMemory() < requiredMemory || gc.freeMemory() < gc.totalMemory () * 0.4) // 메모리가 부족한 경우
{
gc.interrupt(); // 잠자고 있는 쓰레드 gc를 깨운다.
try {
gc.join(100); // 깨운 후에 바로 메모리를 사용할 수 없으니까 잠시 대기!
} catch(interruptedException e) {}
}
gc.usedMemory += requiredMomery; // 메모리 사용
System.out.println("usedMemory : " + gc.useMemory);
g. yield()
- 남은 시간을 다음 쓰레드에게 양보하고, 자신(현재 쓰레드)은 실행대기한다.
- yield()와 interrupt()를 적절히 사용하면, 응답성과 효율을 높일 수 있다.
13) 쓰레드의 동기화(synchronization) : 한 쓰레드가 진행중인 작업을 다른 쓰레드가 간섭하지 못하게 막는 것
- 멀티 쓰레드 프로세스에서는 다른 쓰레드의 작업에 영향을 미칠 수 있다. (멀티 쓰레드는 메모리가 공유되기 때문)
- 진행중인 작업이 다른 쓰레드에게 간섭받지 않게 하려면 '동기화'가 필요
- 동기화하려면 간섭받지 않아야 하는 문장들을 '임계 영역'으로 설정
- 임계영역은 락(lock)을 얻은 단 하나의 쓰레드만 출입가능(객체 1개에 락1개)
14) synchronized를 이용한 동기화
-synchronized로 임계영역(lock이 걸리는 영역)을 설정하는 방법 2가지
ex1) 메서드 전체를 임계 영역으로 지정
public synchronized void calcSun() { // 임계 영역: 다른 쓰레드가 간섭하면 안되는 문장
//... // 한번에 한 쓰레드만 사용할 수 있기 때문에 임계 영역을 최소화 -> 많을 수록 성능이 떨어짐
}
ex2) 특정한 영역을 임계 영역으로 지정
sychronized(객체의 참조변수) { // 최소화 임계 영역 설정
//,,
}
15) wait()과 notify()
a. 사용 이유
- 동기화의 효율을 높이기 위해 wait(),notify()를 사용.
- Object클래스에 정의되어 있으며, 동기화 블록 내에서만 사용할 수 있다.
- wait() : 객체의 lock을 풀고 쓰레드를 해당 객체의 waiting pool에 넣는다.
- notify() : waiting pool에서 대기중인 쓰레드 중의 하나를 깨운다.
- notifyAll() : waiting pool에서 대기중인 모든 쓰레드를 깨운다.
'JAVA' 카테고리의 다른 글
java #16 Object 클래스 총 정리1 (equals(), hashCode(), to String(), join() , StringJoiner) (0) | 2021.05.24 |
---|---|
java #15 와일드 카드, 지네릭 메서드 (0) | 2021.05.23 |
java #13 쓰레드 총 정리 1 (싱글쓰레드, 멀티쓰레드, main쓰레드) (0) | 2021.05.20 |
java #12 Collections, 지네릭스 (0) | 2021.05.19 |
java #11 HashSet, TreeSet (0) | 2021.05.18 |