스퐁지송 개발노트

22.12.06(화) Thread간의 협업 wait,notify,notifyAll 본문

JAVA 입문 시작

22.12.06(화) Thread간의 협업 wait,notify,notifyAll

강준석 2022. 12. 6. 14:15
728x90

wait() : 실행중인 스레드 대기

notify : 대기 중인 스레드를 실행 => 어떤 스레드를 실행 할지 선택 불가능

notifyAll : 모든 대기중인 스레드를 실행

wait()

예시

p1.start();
p2.start();

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

if(this.level == 5) {
	        	 notifyAll();	//대기중인 스레드 실행
	        	 try {
	        		 wait();
	        	 } catch (Exception e) {
	        		 
	        	 }
	         } //p1(실행중이기때문)이 레벨5가 되면 p1는 대기, 대기중인 p2가 실행

예제

package 스레드;

public class ThreadA extends Thread {

	private WorkObject workobject;

	public ThreadA(WorkObject workobject) {
		super();
		this.workobject = workobject;
	}

	public void run() {
		for (int i = 0; i < 10; i++) {
			workobject.methodA();
		}
	}

}
package 스레드;

public class ThreadB extends Thread {

	private WorkObject workobject;

	public ThreadB(WorkObject workobject) {
		super();
		this.workobject = workobject;
	}

	public void run() {
		for (int i = 0; i < 10; i++) {
			workobject.methodB();
		}
	}
}

 

공유자원 스레드문

synchronized : 동기화

 

package 스레드;

public class WorkObject {

	public synchronized void methodA() {
		System.out.println("methodA 실행");

		notify();	//대기중인 "methodB"실행

		try {
			wait();	//methodA 대기
		} catch (Exception e) {

		}
	}

	public synchronized void methodB() {
		System.out.println("methodB 실행");

		notify();	//대기중인 "methodA"실행

		try {
			wait();	//methodB 대기
		} catch (Exception e) {

		}
	}

}

 

 

 

 

메인문

 

package 스레드;

public class Sample08 {

	public static void main(String[] args) {
		
		WorkObject wo = new WorkObject();
		
		ThreadA threadA = new ThreadA(wo); //공유자원 사용
		ThreadB threadB = new ThreadB(wo);
		
		threadA.start();
		threadB.start();

	}

}

 

예제

 

 

package 스레드;

public class RunThread extends Thread{
	
	boolean stop;	//스레드를 on off 하는역활
	
	public void run() {
		while(!stop) {
			System.out.println("스레드 실행중");
		}
		
			System.out.println("스레드 종료");
	}
}

 

 

package 스레드;

public class Sample09 {
											//예외 떠넘기기
	public static void main(String[] args) throws InterruptedException{
		
		RunThread t = new RunThread();
		
		
		t.start();
		
	
			Thread.sleep(3000);
			t.stop = true;
		

	}

}

 

 

 

통장

부모님이 돈 넣음

다 빼서 씀

잔고가 0원 

-반복-

package 스레드;

public class Accout {

	int money;

	synchronized void withdraw() {
		while (money == 0) {
			try {
				wait();
			} catch (Exception e) {

			}
		}
		notifyAll();

		System.out.println(Thread.currentThread().getName() + money + "원 출금");

		money = 0;
	}

	synchronized void deposit() {
		while (money > 0) {
			try {
				wait();
			} catch (Exception e) {

			}
		}
		notifyAll();
		
		money = (int)(Math.random()*5)+ 1;
		money = money * 10000;

		System.out.println(Thread.currentThread().getName() + money + "원 입금");

	}
}

 

자식클래스

 

package 스레드;
//자식클래스
public class Child extends Thread {

	Accout accout;

	public Child(Accout accout) {
		super("자식"); // 스레드 이름 설정
		this.accout = accout;
	}

	public void run() {
		while (true) {
			try {
				if (accout.money > 0) {
					accout.withdraw();
				}
				sleep(10000);
			} catch (Exception e) {

			}
		}
	}

}

 

부모클래스

 

package 스레드;
//부모클래스
public class Parent extends Thread {

	Accout accout;

	public Parent(Accout accout) {
		super("부모"); // 스레드 이름 설정
		this.accout = accout;
	}

	public void run() {
		while (true) {
			try {
				accout.deposit();
				sleep(2000);
			} catch (Exception e) {
				
			}
		}
	}

}

메인문

package 스레드;

public class Main2 {

	public static void main(String[] args) {
		
		Accout acc = new Accout();	//공유자원 객체생성
		Parent p = new Parent(acc); //acc를 사용하는 객체생성
		Child c = new Child(acc); //acc를 사용하는 객체생성
		
		p.start();
		c.start();
		

	}

}

 

Demon Thread

Thread를 보조

일반 Thread가 종료되면  Demon Thread도 종료

 

package 스레드2;

public class Demon extends Thread {

	public void run() {
		while (true) {
			System.out.println(getName());

			try {
				sleep(500);
			} catch (Exception e) {
			}
		}

	}
}

 

package 스레드2;

public class Sample01 {

	public static void main(String[] args) {

		Demon t1 = new Demon();
		Demon t2 = new Demon();

		t1.setDaemon(true);
		t2.setDaemon(true);

		t1.start();
		t2.start();

		try {
			Thread.sleep(5000);
		} catch (Exception e) {

		}
		System.out.println("main 종료");

	}

}

문서작성 시작
자동저장
자동저장
자동저장
자동저장
문서작성 종료

 

스레드 그룹

 

메인문

 

package 스레드2;

public class Sample03 {

	public static void main(String[] args) {
		
		ThreadGroup group = new ThreadGroup("Group1");
		
		MyThread t1 = new MyThread(group, "first");
		MyThread t2 = new MyThread(group, "second");
		MyThread t3 = new MyThread(group, "third");
		
		t1.start();
		t2.start();
		t3.start();
		
		try {
			Thread.sleep(3000);
		} catch (Exception e) {
			
		}
		
		group.interrupt(); //강제로 예외를 만들어 종료
	}

}

 

서브문

 

package 스레드2;

public class MyThread extends Thread {

	MyThread(ThreadGroup group, String name) {
		super(group, name);
	}

	public void run() {
		while (true) {
			System.out.println(getName());

			try {
				sleep(500);
			} catch (Exception e) {
				break; //반복끝내기
			}
		}
		System.out.println(getName()+"종료"); //대기가 있을때 while문이 반복 종료시 실행됨
	}
	
	}

third
first
second
first
third
second
second
third
first
third
first
second
first
third
second
first
second
third
first종료
second종료
third종료


예제

게임만들기

 

내 캐릭터 와 몬스터가 싸워서 동시에 치고받고 싸운다

기본 데미지는 1~10;

10% 확률로 스킬사용(데미지 30고정)

둘 다 체력 100;

공격 쿨타임 1~3초

체력이 0이 되면 종료

 

유저클래스

package 게임;

public abstract class User {
	
	String userID;
	int hp;

}

 

오버라이딩 클래스

 

 

package 게임;

public class Charactor extends User implements Msg{

	public Charactor(String userID,int hp) {	
		this.userID = userID;
		this.hp=hp;
		
	}

	@Override
	public void attackMsg(int dam) {
		System.out.println(this.userID + "가 상대에게"+dam+"의 데미지를 입힙니다.");
		
	}

	@Override
	public void userSkillMsg() {
		System.out.println(this.userID + "가 상대에게 30의 스킬 데미지를 입힙니다.");
		
	}

	@Override
	public void hpMsg() {
		System.out.println("남은 체력 : " + this.hp);
		
	}

	@Override
	public void endMsg() {
		System.out.println(this.userID + " 승리");		
	}
	
	
}

 

 

플레이컴퓨터클래스

package 게임;
//컴퓨터
public class PlayCom extends Thread{
	
	private Charactor user;
	private Charactor com;

	public PlayCom(Charactor user, Charactor com) {
		this.user = user;
		this.com = com;
	}

	public void run() {
		      int damage;
		      int coolTime;
		      
		      try {
		         while(true) {
		            coolTime = ((int)(Math.random() *3) +1 ) * 1000; //1~3초의 램덤시간
		            Thread.sleep(coolTime); //1~3초의 램덤 시간
		            
		            if((int)(Math.random()*10)==4) { //10%ㅎ확률로 스킬사용 //Math.random() = 0~1사이의 수(0.0~0.9)그러므로 10을 곱하면 1~9사이의 수
		            	com.userSkillMsg();
		            	user.hp-=30; //상대방의 체력 -30
		            }else {
		            	damage = (int)(Math.random()*10)+1;
		            	com.attackMsg(damage);
		            	user.hp -= damage; //10%확률로 스킬 발동 안될시 그냥 기본공격
		            }
		            if(user.hp<=0) { //채력이 0되면 종료
		            	com.endMsg();
		            	System.exit(0);
		            }
		            System.out.println(user.userID+"의 남은 체력 : "+ user.hp);
		         }
		      }catch(Exception e) {
		    	  
		      }
		   }
}

플레이유저클래스

package 게임;
//유저
public class PlayerUser extends Thread {

	private Charactor user;
	private Charactor com;

	public PlayerUser(Charactor user, Charactor com) {
		this.user = user;
		this.com = com;
	}

	public void run() {
		      int damage;
		      int coolTime;
		      
		      try {
		         while(true) {
		            coolTime = ((int)(Math.random() *3) +1 ) * 1000;
		            Thread.sleep(coolTime);
		            
		            if((int)(Math.random()*10)==4) {
		            	user.userSkillMsg();
		            	com.hp-=30;
		            }else {
		            	damage = (int)(Math.random()*10)+1;
		            	user.attackMsg(damage);
		            	com.hp -= damage;
		            }
		            if(com.hp<=0) {
		            	user.endMsg();
		            	System.exit(0);
		            }
		            System.out.println(com.userID+"의 남은 체력 : "+ com.hp);
		         }
		      }catch(Exception e) {
		    	  
		      }
		   }

}

 

실행 메인클래스

 

package 게임;

import java.util.Scanner;

public class Main {

	public static void main(String[] args) {
		
		Scanner sc = new Scanner(System.in);
		String userID;
		
		System.out.print("유저 아이디 입력 : ");
		userID = sc.next();ㅁ
		
		Charactor user = new Charactor(userID, 100);
		Charactor com = new Charactor("티모", 100);
		
		PlayerUser playuser = new PlayerUser(user, com);
		PlayCom playcom = new PlayCom(user, com);
		
		playuser.start();
		playcom.start();

	}

}
728x90

'JAVA 입문 시작' 카테고리의 다른 글

22.12.08(목) 문제풀이 for, while, 배열  (0) 2022.12.08
22.12.07(수) 입출력 스트림(Stream)  (2) 2022.12.07
22.12.06(화) Thread  (0) 2022.12.06
22.12.05(월) 스트림 가공  (0) 2022.12.05
22.12.05(월) 스트림  (0) 2022.12.05
Comments