상세 컨텐츠

본문 제목

자바 스레드 관련

본문

반응형

 

 

 

=================================

=================================

=================================

 

 

 

출처: http://jangsalt.tistory.com/22

 

 

[Java] Thread의 정지

Thread.stop가 추천 되지 않는 이유

본질적으로 안전하지 않기 때문입니다.
Thread를 정지하면, 그 Thread가 잠근 모든 모니터의 락이 해제됩니다.
(ThreadDeath 예외가 스택까지 전해지면, 모니터의 락이 해제된다.)
이러한 모니터에 의해서 이전 보호되고 있던 오브젝트가 정합성이 없는 상태가 되면, 다른 Thread도, 이러한 오브젝트가 정합성의 없는 상태에 있다고 봅니다.
그러한 오브젝트는 망가진오브젝트가 됩니다.
망가진 오브젝트에 대해서 Thread가 조작을 실행하면, 예기치 않은 결과가 될 가능성이 있습니다. 이 동작은, 미묘하고 검출이 곤란한 경우와 확실히 통지되는 경우가 있습니다.
체크되지 않는 것 외의 예외와는 달라,ThreadDeath는, 스렛드를 그대로 강제적으로 종료합니다. 이 때문에 유저는 프로그램이 망가질 가능성이 경고되지 않습니다.
프로그램이 망가지거나, 실제로 손상을 받은 것이 나중에 밝혀지게 됩니다. 

Thread.stop 대신에 무엇을 사용해야 하는가

stop 의 대신으로 대부분이 타겟스레드의 실행을 정지해야 할 일을 나타내는 변수를 변경하는 코드를 사용합니다.
타겟스레드는 이 변수를 정기적으로 검사해 실행을 정지해야 할 일을 변수가 나타내 보이고 있는 경우에스레드의 run 메소드로부터 통상의 방법으로 복귀할 필요가 있습니다.
이것은 Java 소프트웨어의 튜토리얼에서 추천 하고 있는 방법입니다.
정지 요구의 즉시 통신을 확실히 하려면 변수를 volatile으로 하거나 변수에서 액세스를 동기화해야 할 필요가 있습니다. 

예를 들어, 애플릿에 다음의 start,stop, 및 run 메소드가 포함되어 있다고 합니다. 
private Thread blinker;

public void start() {
  blinker = new Thread(this);
  blinker.start();
}

public void stop() {
  blinker.stop(); // UNSAFE!
}

public void run() {
  Thread thisThread = Thread.currentThread();
  while (true) {
    try {
      thisThread.sleep(interval);
    } catch (InterruptedException e){
    }
    repaint();
  }
}
애플릿의 stop 및 run 메소드를 다음의 코드와 옮겨놓는 것으로 Thread.stop을 사용하지 않고 끝납니다. 
private volatile Thread blinker;

public void stop() {
  blinker = null;
}

public void run() {
  Thread thisThread = Thread.currentThread();
  while (blinker == thisThread) {
    try {
      thisThread.sleep(interval);
    } catch (InterruptedException e){
    }
    repaint();
  }
}

오랫동안 (입력 등을) 대기하고 있는 스레드는 어떻게 하면 정지할 수 있습니까

그 목적으로는,Thread.interrupt 을 사용합니다.위와 같을 상태에 대해 응하는시그널 기구를 사용할 수 있습니다만,상태 변경 (앞의 예에서는 blinker = null) 후에, Thread.interrupt을 호출해 대기 상태에 끼어들 수 있습니다. 
public void stop() {
  Thread moribund = waiter;
  waiter = null;
  moribund.interrupt();
}
이 방법에서는, 세치기 예외를 캐치 하지만, 처리할 준비가 되어 있지 않은 메소드는 그 예외를 재선언하는 것이 중요합니다.
여기서 「재쓰로우」는 아니고 「재선언」이라고 쓴 것은, 예외를 언제나 재슬로우 할 수 있다고는 할 수 없기 때문입니다.
InterruptedException을 캐치 한 메소드가, 확인이 끝난 예외를 스로우 하도록 선언되어 있지 않은 경우는,다음과 같은 정해진 규칙에 의해 스스로 재할당을 할 필요가 있습니다. 

Thread.currentThread().interrupt();
이것에 의해, 스레드는, 가능한 한 빨리 InterruptedException을 재발행할 수 있게 됩니다. 

스레드가 Thread.interrupt에 응답하지 않으면 어떻게 됩니까

어플리케이션 독자적인 기법이 사용 가능한 경우도 있습니다.
예를 들어, 스렛드가 기존의 소켓상에서 대기하고 있는 경우는, 소켓을 닫는 것으로 스렛드를 즉시 복귀시킬 수 있습니다.
그러나, 유감스럽지만, 범용적으로 사용할 수 있는 기법은 없습니다.
대기하고 있는 스렛드가 Thread.interrupt 에 응답하지 않는 모든 상황에서는, 
그 스렛드는 Thread.stop 에도 응답하지 않는 것에 주의해 주세요.
그러한 상황으로서는,의도적인 서비스 방해 공격이나 ,thread.stop과 thread.interrupt가적절히 기능하지 않는 입출력 조작등이 있습니다.

나) 결론을 말하자면 stop은 비추천이므로 다른 방법중에 .. 루프등 돌면서 선언해둔 변수가, 끝나는 지점인가 등을 통해종료 할 수 밖에 없다. 다른 방법이 있으면 좀 알려주었으면 ...

출처 : http://blog.empas.com/urusaina/26851511

 

 

 

=================================

=================================

=================================

 

 

출처: http://gangzzang.tistory.com/75

 

 

Thread API : http://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html

Thread Group API : http://docs.oracle.com/javase/7/docs/api/java/lang/ThreadGroup.html 

 

1. 프로세스와 쓰레드

- 프로세스(Process) : 실행 중인 프로그램(Program), 자원(resources)과 쓰레드로 구성, 공장에 비유된다.

- 쓰레드(Thread) : 프로세스 내에서 실제 작업을 수행한다, 모든 프로세스는 하나 이상의 쓰레드를 가지고 있다, 일꾼에 비유된다.

- 싱글쓰레드 프로세스 = 자원 + thread

- 멀티쓰레드 프로세스 = 자원 + thread + thread +  . . .

 

2. 멀티쓰레딩

- 하나의 프로세스 내에서 여러 쓰레드가 동시에 작업을 수행하는 것

- 아주 짧은 시간 동안 여러 작업을 번갈아 가며 수행함으로써 동시에 여러 작업이 수행되는 것처럼 보이게 하는 것

- CPU의 사용률을 향상시킨다.

- 자원을 보다 효율적으로 사용할 수 있다.

- 사용자에 대한 응답성이 향상된다.

- 작업이 분리되어 코드가 간결해진다.

- 동기화(synchronization), 교착상태(deadlock) 같은 문제들을 고려해야 한다.

- 각 쓰레드가 효율적으로 고르게 실행될 수 있게 해야 한다.

 

3. 쓰레드의 구현과 실행

- 구현하는 두가지 방법은 Thread 클래스를 상속받는 방법과 Runnable 인터페이스를 구현하는 방법이 있다.

- 다른 클래스를 상속받을때에는 Runnable 인터페이스를 구현하는 방법이 일반적이다.

- 한번 사용한 쓰레드는 다시 재사용할 수  없다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
class Thread1 extends Thread {
    public void run() {
        for (int i = 0; i < 5; i++) {
            System.out.println(getName()); // 조상 Thread의 getName()을 호출
        } // for
    } // run
} // Thread1
 
class Thread1_1 implements Runnable {
    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            // Thread.currentThread(); // 현재 실행 중인 Thread를 반환한다.
            System.out.println(Thread.currentThread().getName());
        } // for
    } // run
} // Thread1_1
 
public class ThreadTest {
    public static void main(String[] args) {
        Thread1 t1 = new Thread1();
         
        Thread1_1 t = new Thread1_1();
        Thread t2 = new Thread(t); // 생성자 Thread(Runnable target)
         
        t1.start();
        t2.start();
    } // main
} // ThreadTest
 
/*
 * 결과
 *
 * Thread-0
 * Thread-0
 * Thread-0
 * Thread-0
 * Thread-0
 * Thread-1
 * Thread-1
 * Thread-1
 * Thread-1
 * Thread-1
 */

4. start(), run()

- run()을 호출하는 것은 생성된 쓰레드를 실행시키는 것이 아니라 단순히 클래스에 속한 메서드 하나를 호출하는 것이다.

- start()는 새로운 쓰레드가 작업을 실행하는데 필요한 호출스택을 생성한 다음에 run()을 호출해서 저장되게 한다.

- 실행 중인 사용자 쓰레드가 하나도 없을 때 프로그램은 종료된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class Human2 extends Thread {
    String name;
 
    public Human2(String name) {
        this.name = name;
    } // Human2 생성자
     
    public void run() {
        for (int i = 1; i <= 10; i++) {
            System.out.println(name + " 이(가) " + "음식" + " 을(를) 먹어요 " + i);
             
            try {
                Thread.sleep(500);
            } catch (Exception e) {
                e.printStackTrace();
            } // try - catch
        } // for
    } // run
} // Human
 
public class ThreadTest2 {
    public static void main(String[] args) {
        Human2 human1 = new Human2("갱짱");
        Human2 human2 = new Human2("이갱짱");
         
        //human1.run();
        //human2.run();
        human1.start();
        human2.start();
    } // main
} // ThreadTest

5. 싱글쓰레드와 멀티쓰레드

- 싱글쓰레드 : 두 개의 작업을 하나의 쓰레드로 처리하는 경우

- 멀티쓰레드 : 두 개의 작업을 두개의 쓰레드로 처리하는 경우

- 단순히 CPU만을 사용하는 계산작업이라면 작업전환(context switching)에 시간이 안걸리는 싱글쓰레드가 효율적이다.

- 하지만 CPU이외의 자원을 사용하는 작업의 경우에는 멀티쓰레드 프로세스가 더 효율적이다.

 

6. 쓰레드의 우선순위(Proiority)

- 우선순위라는 속성(멤버변수)을 가지고 있는데, 이 우선순위의 값에 따라 쓰레드가 얻는 실행시간이 달라진다.

- 수행하는 작업의 중요도에 따라 쓰레드의 우선순위를 서로 다르게 지정하여 특정 쓰레드가 더 많은 작업시간을 갖도록 할 수 있다.

- 쓰레드가 가질 수 있는 우선순위의 범위는 1 ~ 10 이며, 숫자가 높을수록 우선순위가 높다.

- 쓰레드의 우선순위는 쓰레드를 생성한 쓰레드로부터 상속받는다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
// 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 : 보통우선순위
 
class Thread_1 extends Thread {
    public void run() {
        for (int i = 0; i < 300; i++) {
            System.out.print("-");
            for (int x = 0; x < 10000000; x++); // 작업을 지연시키기 위한 for 문
        } // for
    } // run
} // Thread_1
 
class Thread_2 extends Thread {
    public void run() {
        for (int i = 0; i < 300; i++) {
            System.err.print("|");
            for (int x = 0; x < 10000000; x++); // 작업을 지연시키기 위한 for 문
        } // for
    } // run
} // Thread_2
 
public class ThreadPriorityTest {
    public static void main(String[] args) {
        Thread_1 th1 = new Thread_1();
        Thread_2 th2 = new Thread_2();
         
        th2.setPriority(8);
         
        System.out.println("Priority of th1 (-) : " + th1.getPriority());
        System.out.println("Priority of th2 (|) : " + th2.getPriority());
         
        th1.start();
        th2.start();
    } // main
} // ThreadPriorityTest
 
/*
 * 결과
 *
 * Priority of th1 (-) : 5
 * Priority of th2 (|) : 7
 * -||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 */

6. 쓰레드 그룹(thread group)

- 서로 관련된 쓰레드를 그룹으로 묶어서 다루기 위한 것.

- 쓰레드 그룹에 다른 쓰레드 그룹을 포함 시킬 수 있다. 보안상의 이유로 도입된 개념이다.

- 자신이 속한 쓰레드 그룹이나 하위 쓰레드 그룹은 변경할 수 있지만 다른 쓰레드 그룹의 쓰레드를 변경할 수는 없다.

- 모든 쓰레드는 반드시 하나의 쓰레드 그룹에 포함되어 있어야 한다.

- 쓰레드 그룹을 지정하지 않고 생성한 쓰레드는 'main쓰레드 그룹'에 속한다.

- 쓰레드를 쓰레드 그룹에 포함시키려면 Thread의 생성자를 이용해야한다.


7. 데몬 쓰레드(daemon thread)

- 일반 쓰레드(non-daemon thread)의 작업을 돕는 보조적인 역할을 수행한다.

- 일반 쓰레드가 모두 종료되면 자동적으로 종료된다.

- 가비지컬렉터, 워드프로세서의 자동저장, 화면자동갱신 등에 사용된다.

- 무한루프와 조건문을 이용해서 실행 후 대기하다가 특정 조건이 만족되면 작업을 수행하고 다시 대기하도록 작성한다.

- boolean is Daemon() : 쓰레드가 데몬 쓰레드인지 확인한다. 데몬 쓰레드이면 true를 반환한다.

- void setDaemon(boolean on) : 쓰레드를 데몬 쓰레드로 또는 사용자 쓰레드로 변경한다. 매개변수 on의 값을 true로 지정하면 데몬 쓰레드가 된다.

- setDaemon은 반드시 start()를 호출하기 전에 실행되어야 한다.

 

8. 쓰레드의 실행제어

- 쓰레드의 생명 주기

 

 

 

- 쓰레드의 스케줄링과 관련된 메서드

 

 반환형  메서드  설명 
 void  interrupt()   sleep()이나 join()에 의해 일시정지상태인 쓰레드를 실행 대기 상태로 만든다.
 해당 쓰레드에서는 InterruptedException이 발생함으로써 일시정지상태를 벗어나게 된다. 
 void
 void

 void
 join()
 join(long millis)  
 join(long millis, int nanos)
 지정된 시간동안 쓰레드가 실행되도록 한다.
 지정된 시간이 지나거나 작업이 종료되면 join()을 호출한 쓰레드로 다시 돌아와 실행을 계속한다.
 void  resume()  suspend()에 의해 일시정지상태에 있는 쓰레드를 실행대기상태로 만든다. 
 static void
 static void
 sleep(long millis)
 sleep(long millis, int nanos)
  지정된 시간(천분의 일초 단위)동안 쓰레드를 일시정지시킨다.
  지정한 시간이 지나고 나면, 자동적으로 다시 실행대기상태가 된다.
 void  stop()  쓰레드를 즉시 종료시킨다. 교착상태(dead-lock)에 빠지기 쉽기 때문에 deprecated 되었다. 
 void  suspend()  쓰레드를 일시 정지시킨다. resume()을 호출하면  
 static void  void yield()  실행 중에 다른 쓰레드에게 양보(yield)하고 실행대기상태가 된다. 

 

 

- 쓰레드의 상태

 

 상태  설명 
 NEW   쓰레드가 생성되고 아직 start()가 호출되지 않은 상태 
 RUNNABLE   실행 중 또는 실행 가능한 상태 
 BLOCKED  동기화블럭에 의해서 일시정지된 상태(LOCK이 풀릴 때 까지 기다리는 상태) 
 WAITING, TIMED_WAITING   쓰레드의 작업이 종료되지는 않았지만 실행가능하지 않은(unrunnable) 일시 정지상태, TIMED_WAITING은 일시정지시간이 지정된 경우를 의미 
 TERMINATED  쓰레드의 작업이 종료된 상태 

 

 

- 쓰레드를 생성하고 start()를 호출하면 바로 실행되는 것이 아니라 실행대기열(큐와같은 구조)에 저장되어 자신의 차례가 될 때까지 기다려야 한다.

- 실행대기상태에 있다가 자신의 차례가 되면 실행상태가 된다.

- 주어진 실행시간이 다되거나 yield()를 만나면 다시 실행대기상태가 되고 다음 차례의 쓰레드가 실행상태가 된다.

- 실행 중에 suspend(), sleep(), wait(), join(), I/O block에 의해 일시정지상태가 될 수 있다. I/O block은 입출력작업에서 발생하는 지연상태를 말한다.

- 지정된 일시정지시간이 다되거나(time-out), notify(), resume(), interrupt()가 호출되면 일시정지 상태를 벗어나 다시 실행대기열에 저장되어 자신의 차례를 기다리게 된다.

- 실행을 모두 마치거나 stop()이 호출되면 쓰레드는 소멸된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
// 한 쓰레드의 작업의 중간에 다른 쓰레드의 작업이 필요할 때 join()을 사용한다.
 
class ThreadJoin_1 extends Thread {
    public void run() {
        for (int i = 0; i < 300; i++) {
            System.out.print("-");
        } // for
    } // run
} // ThreadJoin_1
 
class ThreadJoin_2 extends Thread {
    public void run() {
        for (int i = 0; i < 300; i++) {
            System.out.print("+");
        } // for
    } // run
} // ThreadJoin_1
 
public class ThreadJoinTest {
    public static void main(String[] args) {
        ThreadJoin_1 th1 = new ThreadJoin_1();
        ThreadJoin_2 th2 = new ThreadJoin_2();
         
        th1.start();
        try {
            th1.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } // try - catch
        System.out.println();
        th2.start();
    } // main
} // ThreadJoinTest
 
/*
 * 결과
 *
 * ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 * ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 */
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
// sleep()는 쓰레드를 지정된 시간동안 일시정지 상태가 되도록 한다. 천분의 일초 단위이다.
// suspend()가 호출되면 쓰레드는 일시정지 상태가 되고
// resume()이 호출되면 다시 실행 대기 상태가 된다.
// stop()을 호출하면 쓰레드는 즉시 종료된다.
 
// interrupt()는 InterruptedException을 발생시켜서, sleep(), join(), wait()에 의해 일시정지상태인 쓰레드를 실행 대기 상태로 만든다.
// 그러나, 호출되었을 때 sleep(), join(), wait()에 의한 일시정지상태가 아니라면 아무 일도 일어나지 않는다.
 
class MyTherdTest implements Runnable {
    boolean suspended = false;
    boolean stopped = false;
     
    Thread th;
     
    MyTherdTest(String name) {
        th = new Thread(this, name); // Thread(Runnable r, String name)
    } // MyMyTherdTest 생성자
     
    @Override
    public void run() {
        String name = Thread.currentThread().getName();
         
        while (!stopped) {
            if (!suspended) {
                System.out.println(name);
                try {
                    Thread.sleep(1000);
                } catch (Exception e) {
                    System.out.println(name + " - interrupted");
                } // try - catch
            } else {
                Thread.yield();
            } // if
        } // while
        System.out.println(name + " - stopped");
    } // run
     
    public void suspend() {
        suspended = true;
        th.interrupt();
        System.out.println("interrupt() in suspend()");
    } // suspend
     
    public void resume() {
        suspended = false;
    } // resume
     
    public void stop() {
        stopped = true;
        th.interrupt();
        System.out.println("interrupt() in stop()");
    } // stop
     
    public void start() {
        th.start();
    } // start
} // MyTheradTest
 
public class TheradTest {
    public static void main(String[] args) {
        MyTherdTest th1 = new MyTherdTest("●");
        MyTherdTest th2 = new MyTherdTest("★★");
        MyTherdTest th3 = new MyTherdTest("◆◆◆");
         
        th1.start();
        th2.start();
        th3.start();
         
        try {
            Thread.sleep(2000);
            th1.suspend();
            Thread.sleep(2000);
            th2.suspend();
            Thread.sleep(3000);
            th1.resume();
            Thread.sleep(3000);
            th1.stop();
            th2.stop();
            Thread.sleep(2000);
            th3.stop();
        } catch (Exception e) {
            e.printStackTrace();
        } // try - catch
    } // main
} // TheradTest
 
/*
 * 실행 결과
◆◆◆
★★
◆◆◆
★★
interrupt() in suspend()
◆◆◆
★★
● - interrupted
★★
◆◆◆
◆◆◆
interrupt() in suspend()
★★
★★ - interrupted
◆◆◆
◆◆◆
◆◆◆
◆◆◆
◆◆◆
◆◆◆
interrupt() in stop()
interrupt() in stop()
★★ - stopped
● - stopped
◆◆◆
◆◆◆
interrupt() in stop()
◆◆◆ - interrupted
◆◆◆ - stopped
*/

9. 쓰레드의 동기화

- 멀티쓰레드 프로세스의 경우 여러 쓰레드가 같은 프로세스 내의 자원을 공유해서 작업을 하기 때문에 동기화가 필요하다.

- 한 번에 하나의 쓰레드만 객체에 접근할 수 있도록 객체에 락(lock)을 걸어서 데이터의 일관성을 유지한다.

- synchronized 키워드를 통해 작업과 관련된 공유데이터에 lock를 건다.

- 특정 객체에 lock을 걸 때 : synchronized(객체의 참조변수) { /* ... */ }

- 메서드에 lock을 걸 때 : public synchronized void calcSum() { /* ... */ }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
class ATM implements Runnable {
    private long depositeMoney = 10000;
 
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            try {
                Thread.sleep(1000);
            } catch (Exception e) {
                e.printStackTrace();
            } // try - catch
 
            if (getDepositeMoney() <= 0)
                break;
 
            synchronized (this) {
                withDraw(1000);
            } // synchronized
        } // for
    } // run
 
    public void withDraw(long howMuch) {
        if (getDepositeMoney() > 0) {
            depositeMoney -= howMuch;
            System.out.print(Thread.currentThread().getName() + " , ");
            System.out.printf("잔액 : %,d 원 %n", getDepositeMoney());
        } else {
            System.out.print(Thread.currentThread().getName() + " , ");
            System.out.println("잔액이 부족합니다");
        } // if
    } // withDraw
 
    public long getDepositeMoney() {
        return depositeMoney;
    } // getDepositeMoney
} // ATM
 
public class SynchronizedTest {
    public static void main(String[] args) {
        ATM atm = new ATM();
 
        Thread mother = new Thread(atm, "mother");
        Thread son = new Thread(atm, "son");
 
        mother.start();
        son.start();
    } // main
} // SynchronizedTest

10. wait(), notify()

- 동기화의 효율을 높이기 위해 사용한다. 

- Object 클래스의 정의되어 있으므로, 모든 객체에서 호출이 가능하다.

- 동기화 블록내에서만 사용할 수 있다.

- wait() : 객체의 lock을 풀고 해당 객체의 쓰레드를 대기상태로 둔다.

- notify() : 대기중인 쓰레드 중의 하나를 깨운다.

- notifyAll() : 대기중인 모든 쓰레드를 깨운다. 호출된 객체의 대기 중인 쓰레드만 해당 된다.

 

 

 

=================================

=================================

=================================

 

 

 

반응형


관련글 더보기

댓글 영역