쓰레드(Tread)
프로그램
프로세스
- 실행된 프로그램
- 운영체제로부터 시스템 자원을 할당받는 작업의 단위.
- JAVA프로그램은 운영체제 대신 JVM에 의해 실행된다.
- 모든 쓰레드가 종료되어야 프로세스도 종료된다.
System.exit(0);으로 강제종료하면 모두 종료된다.
쓰레드
- 프로세스의 특정한 수행 경로
- 프로그램 처리 경로.
- 직렬적이다.
- JVM에 의해 스케줄링 된다. (각 쓰레드의 순서를 지정하는 기능?)
멀티 쓰레드
- 하나의 프로세스를 동시에 처리하는 것처럼
보이지만 사실은 매우 짧은 단위로 분할해서
차례로 처리한다(병렬적).
- 여러개의 경로를 가질 수 있게 하고
한 개의 처리경로를 여러개로 나누어
동시 작업이 가능하다.
- 장점
효율성 증가
처리량 증가
처리비용 감소
- 단점
복잡하고 설계가 어려움.
자원의 공유 문제
하나의 쓰레드 문제 발생시 모두 문제 발생
교착상태(DeadLock)
: 멀티 쓰레드 중 쓰레드 간에 대기 상태가 종료되지 않아서
무한정 대기만 하는 비정상적인 상태
하나의 쓰레드를 끊어주거나, 모두 다 깨워주는 방법으로 교착상태를 해결한다.
멀티 쓰레드 구현 방법
① Tread 클래스 상속
② Runnable 인터페이스 상속
run() : 쓰레드 구현
start() : 스케줄링 후 쓰레드 실행
join()
쓰레드 사용시 쓰레드 종료 전 다음 로직을 수행하면
예기치 못한 오류가 발생한다.
그러므로 join()을 사용하여 먼저 스케줄링 할 수 있다.
Thread 클래스로 extends한 경우
package day22;
public class Thread1 extends Thread {
String data;
public Thread1() {}
public Thread1(String data) {
super();
this.data = data;
}
@Override
public void run() {
//쓰레드 구현
for (int i = 0; i < 10; i++) {
System.out.println(data);
//alt + shift + z
try {Thread.sleep(500);} catch (Exception e) {;}
}
}
}
Runnable 인터페이스로 implements한 경우
package day22;
public class Thread2 implements Runnable {
String data;
public Thread2() {}
public Thread2(String data) {
super();
this.data = data;
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(data);
try {Thread.sleep(500);} catch (InterruptedException e) {;}
}
}
}
package day22;
public class ThreadTest {
public static void main(String[] args) {
//up casting
Thread2 t1 = new Thread2("!");
Thread2 t2 = new Thread2("?");
//start로 스케줄링을 하기 위하여
//Runnable객체를 생성자로 전달한다.
Thread th1 = new Thread(t1);
Thread th2 = new Thread(t2);
//멀티 쓰레드(2개의 쓰레드)
//전달 받은 Runnable 객체에 있는 run()을 스케줄링 해준다.
th1.start();
th2.start();
try {
//가장 먼저 작업하기 위해 join()을 사용한다.
th1.join();
th2.join();
} catch (InterruptedException e) {;}
//join()을 사용하지 않은 main쓰레드는 위의 작업이 모두
//완료된 후 실행된다.
System.out.println("main 메소드 종료");
// Thread1 t1 = new Thread1("★");
// Thread1 t2 = new Thread1("♥");
//
// t1.start();
// t2.start();
// t1.run();
// t2.run();
}
}
package zoo;
public class Animal implements Runnable {
String sound;
public Animal() {}
public Animal(String sound) {
super();
this.sound = sound;
}
//자원
public void makeSomeNoise() {
for (int i = 0; i < 10; i++) {
System.out.println(sound);
try {Thread.sleep(500);} catch (InterruptedException e) {;}
}
}
@Override
public void run() {
makeSomeNoise();
}
}
package zoo;
public class Zoo {
public static void main(String[] args) {
//동물 3마리가 동물원에서 울음소리를 낸다.
//두마리 동물은 동시에 10번 울고
//남은 동물은 마지막에 10번 운다.
//멀티 쓰레드로 구현한다(Runnable 사용)
Animal[] animals = { new Animal("어흥"),
new Animal("으엉"), new Animal(".$#@#..")};
Thread[] ths = new Thread[animals.length];
for (int i = 0; i < ths.length; i++) {
ths[i] = new Thread(animals[i]);
}
ths[0].start();
ths[1].start();
try {
ths[0].join();
ths[1].join();
} catch (InterruptedException e) {;}
ths[2].start();
}
}
동기화(Synchronuzed)
: ① 특정 자원에 쓰레드가 동시에 접근하지 못하도록 제한하는 기법
, ② 각 쓰레드를 사용자가 직접 제어하기 위해 사용하는 기법
은행 출금 예)
package atm;
public class ATM implements Runnable{
int money = 10000;
public void withdraw(int money) {
this.money -= money;
System.out.println(Thread.currentThread().getName() + "이(가) " + money + "원 출금");
System.out.println("현재 잔액 : " + this.money + "원");
}
@Override
public void run() {
for (int i = 0; i < 5; i++) {
synchronized (this) {
withdraw(1000);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
;
}
}
}
}
}
package atm;
public class CU {
public static void main(String[] args) {
ATM atm = new ATM();
Thread mom = new Thread(atm, "엄마");
Thread son = new Thread(atm, "아들");
mom.start();
son.start();
}
}
빵 만드는 메소드가 실행, 빵이 10개 이상이되면 wait()하고 먹는 메소드가 실행된다.
빵이 0개가 되면 먹는 메소드가 멈추고 빵 만드는 메소드가 실행된다.
package bakery;
public class BakeryPlate {
int breadCnt;
int eatCnt;
synchronized public void makeBread() {
if (breadCnt > 9) {
try {
System.out.println("빵이 가득 찼습니다. 먹으세요.");
wait();
} catch (InterruptedException e) {;}
}
breadCnt++;
System.out.println("빵을 1개 만들었습니다. 총 : " + breadCnt + "개");
}
synchronized public void eatBread() {
if (eatCnt == 20) {
System.out.println("빵이 다 떨어졌습니다.");
}else if(breadCnt < 1) {
System.out.println("기다리세요.");
}else {
breadCnt --;
eatCnt++;
System.out.println("빵을 1개 먹었습니다. 총 : " + breadCnt + "개");
}
//wait상태인 애가 this이다.
this.notify();
}
}
package bakery;
public class Maker implements Runnable{
private BakeryPlate bread = new BakeryPlate();
// public Maker(BakeryPlate bread) {
// super();
// this.bread = bread;
// }
public BakeryPlate getBread() {
return bread;
}
public void setBread(BakeryPlate bread) {
this.bread = bread;
}
@Override
public void run() {
for (int i = 0; i < 20; i++) {
bread.makeBread();
try {Thread.sleep(500);} catch (InterruptedException e) {;}
}
System.out.println("영업 종료");
}
}
package bakery;
import javax.swing.JOptionPane;
public class Bakery {
public static void main(String[] args) {
Maker maker = new Maker();
BakeryPlate bread = maker.getBread();
Thread t = new Thread(maker);
int choice = 0;
String[] menu = {"빵 먹기"};
t.start();
while(true) {
choice = JOptionPane.showOptionDialog(null,
"", "파리바게트", JOptionPane.DEFAULT_OPTION,
JOptionPane.PLAIN_MESSAGE, null, menu, null);
if(choice == -1) {
System.exit(0);
}else {
bread.eatBread();
}
}
}
}
To Do List
Zoo에서
- 클래스로 만들 경우 : 각 동물마다 다른 기능을 가지고있고 다른 기능들을 쓰고자 할 때
- 객체로 만들 경우 : 각 동물의 같은 기능을 사용할 때
- 의존성에 대해서 한번 더 공부!
- up casting 꼭 다시 공부!
?) try/catch가 뭔지
A) 원래 순서를 거스르는? 무언가를 쓸때는 try/catch를 사용. wait, sleep같은 메소드들!

참고) https://coding-factory.tistory.com/280
?) Except와 In,..Except의 차
----- 단축키 -----
ctrl + shift + esc : 작업관리자
-------------------
'JAVA' 카테고리의 다른 글
[WEB]DAY24, 25_ 파일 입출력과 MVC모델(상품 정보 관리 프로그램) (0) | 2020.04.15 |
---|---|
[WEB]DAY23_파일 입출력 (0) | 2020.04.13 |
[WEB]DAY21_MVC(소프트웨어 디자인 설계 패턴) (0) | 2020.04.09 |
[WEB]DAY20_Set(HashSet), Map(HashMap) (0) | 2020.04.09 |
[WEB]DAY19_Wrapper 클래스, 빠른 for문, 제네릭(Generic), 컬렉션 프레임워크(Collection Framework) (0) | 2020.04.07 |