쓰레드 통신 - 신호예제 (신호등)

smkim·2021년 10월 18일
0
post-custom-banner

수정 전 코드

class Car extends Thread { 
	private Road road; // 공유자원인 도로 객체 

	public Car(Road r,String a) { 
		road = r; 
		super(name) // 객체로부터 받아온 이름에서 생성자는 생성자 주기에만 동작한다. 그래서 멤버변수에 값을 따로 저장해준다 > 이건 어느 경우에.. 
	
		
	} 
public void run() { 
	for(int i=0;i<3;i++){
		road.runcar(i); } 
} 
} 

class Bicycle extends Thread { 
	Road road; // 공유자원인 도로 객체 

	public Bicycle(Road r,string b){
		road = r;
		b=super(name);
	} 

public void run() { 
	for(int i=0;i<3;i++){ 
		road.runBicycle(i); } 
} 

} 

class Human extends Thread { 
	Road road; // 공유자원인 도로 객체 

	public Human(Road r,String c){ 
		road = r; 
		c=super(name);
	} 

public void run() { 
	for(int i=0;i<3;i++){ 
		road.walkHuman(i); } 
} 

}

class Road { 
	int signal = 1; // 자동차 신호 
	int signal = 2; // 자전거 신호 
	int signal = 3; // 보행자 신호 

	public synchronized void runCar() { 
		while(signal!=1) { // 자동차의 신호가 1번이 아닐 때 
			try{ 
				wait(); // 자동차는 기다린다. 
			} catch (InterruptedException e) { } 
		} 
		System.out.println(a+ "가 주행한다"); // 자동차 신호가 1번이 맞으므로 차가 주행한다. 근데 왜 a값이 안넘어왔지? 
		// 자동차 신호가 자신의 일을 끝내기 전에 나머지 객체가 일할 수 있도록 신호 바꿔주기 
		if(signal==2 && signal==3){
			notifyAll(); 
		} else { } 
	
	}



	public synchronized void runBicycle() { 
		while(signal!=2){ 
			try{ 
				wait();  //자전거는 기다린다
			} catch (InterruptedException e) { } 
		}
		System.out.println( b + "가 달린다"); // 자전거 신호가 2번이 맞으므로 자전거가 달린다. 
		// 자전거 신호가 자신의 일을 끝내기 전에 나머지 객체가 일할 수 있도록 신호 바꿔주기
		if(signal==1 && signal==3){ 
			notifyAll(); 
		} else { }
	}

	
	public synchronized void walkHuman() { 
		while(signal!=3){ 
			try{ 
				wait(); // 보행자는 기다린다
			} catch(InterruptedException e) { } 
		} 
		System.out.println( c + "가 길을 건넌다");
		// 보행자 신호가 자신의 일을 끝내기 전에 나머지 객체가 일할 수 있도록 신호 바꿔주기
			if(signal==1 && signal==2){
				notifyAll(); 
			} else { }
	}

}


class ThreeSignal {
	public static void main(String[] args) { 

	Road rd = new Road(); // 공유자원인 도로 객체 
	Car car = new Car("자동차",rd); // 자동차 쓰레드 객체 , 공유자원인 도로 객체 공유 
	Bicycle bc = new Bicycle("자전거",rd); // 자전거 쓰레드 객체 
	Human hm = new Human("보행자",rd); // 보행자 쓰레드 객체 

	car.start();
	bc.start();
	hm.start();

} 

} 

수정 후 코드

class Car extends Thread { 
	private Road road; // 공유자원인 도로 객체 

	public Car(Road r) { 
		road = r; 
		} 
	public void run() { 
		for(int i=0;i<3;i++){
			road.drive();
	} 
       } 
} 

class Bike extends Thread { 
	Road road; // 공유자원인 도로 객체 

	public Bike(Road r){
		road = r;
		} 

	public void run() { 
		for(int i=0;i<3;i++){ 
			road.biking(); 	
	}
    } 
} 

class Man extends Thread { 
	Road road; // 공유자원인 도로 객체 

	public Man(Road r){ 
		road = r; 
		} 

	public void run() { 
		for(int i=0;i<3;i++){ 
			road.walk(); 
	} 
   } 

}

class Road { 
	private String signal = "green"; 

	public synchronized void drive() { 
		while(signal!="green") { // 자동차의 신호가 green이 아닐 때 
			try{ 
				wait(); // 자동차는 기다린다. 
			} catch (InterruptedException e) { } 
		} 
		System.out.println("차가 주행한다");
		signal = "yellow"; // 자전거 신호 바꿔주기 
		notifyAll();
		} 
	
	public synchronized void biking() { 
		while(signal!="yellow"){ 
			try{ 
				wait();  //자전거는 기다린다
			} catch (InterruptedException e) { } 
		}
		System.out.println("자전거가 달린다"); // 자전거 신호가 yellow가 맞으므로 자전거가 달린다. 
		// 자전거 신호가 자신의 일을 끝내기 전에 나머지 객체가 일할 수 있도록 신호 바꿔주기
		signal = "red";
		notifyAll();
		} 

	
	public synchronized void walk() { 
		while(signal!="red"){ 
			try{ 
				wait(); // 보행자는 기다린다
			} catch(InterruptedException e) { } 
		} 
		System.out.println("보행자가 길을 건넌다");
		signal = "green"; // 자동차 신호로 바꿔주기
		notifyAll();
			} 
	}




class ThreeSignal2 {
	public static void main(String[] args) { 

	Road rd = new Road(); // 공유자원인 도로 객체 
	Car car = new Car(rd); // 자동차 쓰레드 객체 , 공유자원인 도로 객체 공유 
	Bike bike = new Bike(rd); // 자전거 쓰레드 객체 
	Man man = new Man(rd); // 보행자 쓰레드 객체 

	car.start();
	bike.start();
	man.start();

} 

} 

놓쳤던 부분, 헷갈렸던 부분

  1. 서로 하는 일이 다르면 각각의 쓰레드 클래스로 만들어주자.
  2. private Road road; 처럼 road형의 매개변수는 private형이 좋다. 캡슐화를 할 수록 좋은 프로그램이다. 그러나 꼭 private로 선언할 필요는 없다.
  3. car의 road와 bike의 road Man의 road는 서로 다르다. 각각의 클래스의 멤버변수이다.
  4. main 클래스에서 road 객체를 만들 때 초기값이 없었다. 그러므로 공유자원 클래스 Road에서도 생성자를 만들 필요가 없다.
  5. wait()는 안 깨어날 수도 있기 때문에 try~catch로 예외처리를 꼭 해주어야 한다.
  6. main 클래스에서 객체 선언&생성시 초기값으로 그들이 공유하는 공유자원 객체와 쓰레드 클래스에 넘겨주어야 하는 값들을 초기값으로 지정하는 것을 명심하자.
profile
컴퓨터공학과 학생 brandy 입니다. 개발+기획에 관심이 있지만, 개발 실력이 뛰어나진 않지만 성장하고자 하기 위해 벨로그를 작성합니다.
post-custom-banner

0개의 댓글