이번 포스팅에서는 Thread에서 다루어보았다. 기본 이론과 객체생성 방식, 블록, 동기화, 예제로 구성되어있다.
1. Thread란?
1) 배경지식
- 프로그램과 프로세스 : 프로그램을 ---실행상태로 옮기면---> 프로세스이다.
- 실행상태 : 자원을 일할 수 있게 할당받은 상태
- Tread : 메모리를 할당받은 프로세스에서 실질적인 작업을 수행하는 대상 = 프로세스에서 일하는 일꾼!
2) 프로세스의 실행방식
- 선점형 방식 : 우선순위 순서대로 자원을 할당받아 진행되는 방식 -> 기아현상 발생가능성 있음
- 시간분할 방식 : 시간을 동일하게 배분하여 골고루 실행될 수 있도록 진행하는 방식
>> >>OS(운영체제)의 스케줄러가 이러한 실행과정을 담당한다
*기아현상 : 우선순위가 낮은 프로세스는 평생 자원할당을 받지 못하는 현상
2. 객체 생성 방식
1) 클래스 상속
//무슨 작업을 수행할지 작성해주어야 함
//Tread안의 run이라는 메서드를 오버라이딩하여 작성!
// 기본생성자가 생략되어있음을 알 것!(Th1(){})
class Th1 extends Thread{
public void run() {
for(int i=0; i<=10; i++) {
System.out.println("class로 만든 Tread " +i);
}
}
}
public class Test07 {
public static void main(String[] args) {
Th1 t1 = new Th1();
t1.start(); // "t1아, 일해!"
}
}
: 강제성이 없다는 특징이 있다. Th1(iPhone) 는 Thread(phone)를 상속받았으므로 th1을 객체화(함장이의 iPhone) 하면 바로 사용할 수 있다.
2) 인터페이스 구현
// 인터페이스가 갖는 강제성을 이용하여 오버라이딩
class Th2 implements Runnable{
@Override
public void run() {
for(int i=0; i<=10; i++) {
System.out.println("interface로 만든 Tread " +i);
}
}
}
public class Test07 {
public static void main(String[] args) {
Th2 t2 = new Th2();
Thread t3 = new Thread(t2);
// Thread클래스의 생성자는 오버로딩되어있음
//Thread의 객체들이 독립적으로 일을 수행하고 있다.
t2.start();
t3.start();
}
}
: run의 오버라이딩이 필수이다. Runnuble 클래스 안에 run( )(전화하기) 가 있다고 해서 Th2(Watch)가 Thread(Phone)인것은 아니다. 그래서 Th2를 객체화(함장이의 Watch)하고, Thread도 객체화(함장이의 Phone) 하여 그 인자로 Th2를 넣어주어야한다.(함장이의 phone) --연동--> (함장이의 Whatch)
3. 블록
1) 배경지식
Thead의 생명주기(라이프사이클) = 생성 -> 대기 -> 수행 -> 메모리해제(데드)
수행에서 메모리해제로 넘어가는 과정(->)속에 블록이 존재한다. 블록이란 자원을 할당받지 못하게 막아두는 상태를 의미한다.
2) Sleep
: 블록상태의 가장 대표적인 예시이며, 아래로는 sleep의 사용 예시이다. 이를 출력하면 0.5초 간격으로 메인i++;이 출력된다.
for(int i=1; i<=10; i++) {
System.out.println("메인" + i);
try { //Sleep의 사용
Thread.sleep(500); // 1000 = 1초
} catch (InterruptedException e) {
e.printStackTrace();
}
}
4. 동기화
: Thread는 독립적으로 일을 수행하기 때문에 동기화가 반드시 필요하다. 공유자원을 어떤 Thread가 점유하고 있을때, 다른 Thread의 접근을 막는 방식으로 동기화가 가능하다.
동기화가 필요한 이유는 로직에 대한 고려사항 없이 start로 인해 개별적으로 일을 수행하게 되면, 1번째 구매자의 구매가 끝나지 않았는데 다음 구매자가 구매 진행하고, 티켓의 수가 아직 차감되기 전이므로 그냥 구매 성공 출력 후 -1처리하게된다. 이렇게 되면 정상적인 티켓팅코드를 구현할 수 없다.
1) Synchronized
: Thread가 수행할 메서드앞에 선언하여 동기화가 가능하다. 출력할때마다 순서는 바뀔 수 있어도 메서드의 로직이 정상적으로 수행되어 출력된다.
// 사람들이 공유자원인 티켓을 구매하는 로직
package class01;
// Thread로서 일할수있도록,
//run()메서드 강제해야하므로 인터페이스를 사용하여 생성
class Person implements Runnable{
// pay()를 사용할 수 있도록 Ticketting클래스 객체화!
Ticketting t=new Ticketting();
@Override
public void run() {
t.pay();
}
}
class Ticketting{
static int ticket=2;
synchronized void pay() {
if(ticket>0) {
System.out.println(Thread.currentThread().getName()+"님, 구매성공!");
ticket--;
}
else {
System.out.println(Thread.currentThread().getName()+"님, 구매실패ㅜㅠ");
}
System.out.println("남은티켓: "+ticket);
}
}
public class Test01 {
public static void main(String[] args) {
Person p=new Person();
Thread t1=new Thread(p,"홍길동");
Thread t2=new Thread(p,"아무무");
Thread t3=new Thread(p,"티모");
t1.start();
t2.start();
t3.start();
}
}
[출력확인]
홍길동님, 구매성공!
남은티켓: 1
티모님, 구매성공!
남은티켓: 0
아무무님, 구매실패ㅜㅠ
남은티켓: 0
동기화시에는 항상 데드락(교착상태)을 유의해야한다!
데드락 : 점유에서 벗어나지 못하고 무한정 대기상태가 되는 것
5. 예제
: 가족계좌를 만들고, 잔액이 0원이면 결제되지 않도록 구현하라.
package class01;
import java.util.Random;
//가족은 구매를 할테니 강제적으로 해야하는 행위를 run()에서 재정의
class Familly implements Runnable{
//사용할 클래스의 객체화
Bank b = new Bank(new Random().nextInt(5000)+1);
//가족이면 반드시 결제해라
@Override
public void run() {
b.pay();
}
}
class Bank {
static int money = 10000;
int price;
Bank(int price){
this.price = price;
}
synchronized void pay() {
if(money-price>=0) {
System.out.println(Thread.currentThread().getName()+" "+price+"원 결제 완료");
money-=price;
}else {
System.out.println("결제 실패");
}
}
}
public class Test02 {
public static void main(String[] args) {
Familly f = new Familly();
Thread t1 = new Thread(f, "아빠");
Thread t2 = new Thread(f, "엄마");
Thread t3 = new Thread(f, "언니");
Thread t4 = new Thread(f, "동생");
t1.start();
t2.start();
t3.start();
t4.start();
}
}
[출력확인]
아빠 3098원 결제 완료
동생 3098원 결제 완료
언니 3098원 결제 완료
결제 실패
수정할 사항 -> 금액 랜덤을 객체별로 다르게 할 것!
'JAVA' 카테고리의 다른 글
[MVC] MVC개념 & DAO·VO (0) | 2022.01.15 |
---|---|
[파일 입출력] TXT & 이미지형식 (+Wrapper Class) (0) | 2022.01.14 |
[예외처리] 예외화 & 예외미루기 (0) | 2022.01.13 |
[컬렉션프레임워크] 링크리스트 & 그 외 컬렉션 (0) | 2022.01.12 |
[컬렉션프레임워크] 배열리스트 (0) | 2022.01.11 |