TestJavaSync.java

smkim·2021년 10월 10일
0

[실행 결과]


내 전체 코드

import java.lang.*; 

class Student extends Thread { // 쓰레드 학생 클래스 
	String name; // 학생 이름 
	int hakbun; // 학생 학번 
	int time=System.currentTimeMillis(); //시험 시간 
	
	Student(String n,int h,int t){ 
		super(name);
		super(hakbun); 
		super(time);
	} 
	public void run() { 
		Test.test(int h,String n);
		Test.goBackHome(int h,String n);
		Test.checkProfessor(int h,String n);
		Test.checkTestTime(int h,String n,int h); 
	} 
} 

class Test { // 공유자원 클래스 

void test(int h,String n){ 
	System.out.println(hakbun+"번"+name+"가 JAVA 시험을 보고있다"); 
} 
void goBackHome(int h,String n){ 
	System.out.println(hakbun+"번"+name+"가 집으로 돌아간다"); 
} 
synchronized void checkProfessor(int h,String n) { 
	System.out.println("안유정교수가"+hakbun+"번"+name+"의 시험지를 확인하고 접수했다"); 
	}
void checkTestTime(int h,String n,int h){ 
	if(time>700){
		time.sleep(1.0);
	}
	else { System.out.println(hakbun+"번"+name+"가 시험본 시간은"+time.random()); } 
}

class TestJavaSync { // main 클래스 
	public static void main(String[] args){ 
		Student s1 = new Student("김별이",2020081001,time);
		Student s2 = new Student("유준서",2018081100,time);
		Student s3 = new Student("이지은",2019081077,time);
	
		s1.start();
		s2.start();
		s3.start();
	} 
} 

수정 코드

class Professor { // 공유자원 교수 클래스 
	String name; 
	Professor(String n) { name = n; } 

	synchronized void check_testpaper(Student s) { 
		s.end = System.currentTimeMillis();
		System.out.println(s.number+"번"+s.name+"가 시험본 시간은"+(s.end-s.begin)+"ms");
		if((s.end-s.begin)<=700)
			System.out.println(name+"교수가"+s.number+"번"+s.name+"의 시험지를 확인하고 접수했다");
		else 
			System.out.println(s.number+"번"+s.name+"의 시험지는 time over"); 
	}
} 

class Student extends Thread { 
	Professor prof;
	String name;
	int number; 
	long begin,end; 

 	Student(Professor p,String n,int no){ 
		prof = p;
		name = n; 
		number = no; 
	} 
	public void run() { 
		begin = System.currentTimeMillis(); // end가 없는 이유는 교수님이 시간 check 
		testJava(name,number); // n,no라고 매개변수 값을 주면 어떻게 되지? 
		prof.check_testpaper(this); // 교수 객체가 시험지를 check하는 것이니 prof.check~ 
		goHome(name,number);
	} 

	void testJava(String n,int no){ 
		System.out.println(no+"번"+n+"가 JAVA 시험을 보고있다"); 
		try {                         
			Thread.sleep((int)(Math.random()*1000)); } 
		catch(InterruptedException e) { } 
	} 
	void goHome(String n,int no){ 
		System.out.println(no+"번"+n+"가 집으로 돌아간다");
}
} 

public class TestJavaSync2 { 
	public static void main(String[] args){ 
		Professor p = new Professor("방탄소년단");
		Student s1 = new Student(p,"김별이",2020081001); 
		Student s2 = new Student(p,"이지은",2019081077);
		Student s3 = new Student(p,"유준서",2018081100);
		s1.start();
		s2.start();
		s3.start();
	} 
}

코드 비교
main 클래스 (나)

class TestJavaSync { // main 클래스 
	public static void main(String[] args){ 
		Student s1 = new Student("김별이",2020081001,time);
		Student s2 = new Student("유준서",2018081100,time);
		Student s3 = new Student("이지은",2019081077,time);
	
		s1.start();
		s2.start();
		s3.start();
	} 
} 

main 클래스 (수정)

public class TestJavaSync2 { 
	public static void main(String[] args){ 
		Professor p = new Professor("방탄소년단");
		Student s1 = new Student(p,"김별이",2020081001); 
		Student s2 = new Student(p,"이지은",2019081077);
		Student s3 = new Student(p,"유준서",2018081100);
		s1.start();
		s2.start();
		s3.start();
	} 
}
  1. 공유자원인 교수 객체 선언,생성을 하지 않았다.
  2. time(시간)을 공유하는 것이 아닌 학생들이 교수 객체를 공유하는 것이므로, 교수 객체를 공유하도록 해야 한다 (같은 메모리 상에 있어 공유 가능)

Student 쓰레드 클래스 (나)

import java.lang.*; 

class Student extends Thread { // 쓰레드 학생 클래스 
	String name; // 학생 이름 
	int hakbun; // 학생 학번 
	int time=System.currentTimeMillis(); //시험 시간 
	
	Student(String n,int h,int t){ 
		super(name);
		super(hakbun); 
		super(time);
	} 
	public void run() { 
		Test.test(int h,String n);
		Test.goBackHome(int h,String n);
		Test.checkProfessor(int h,String n);
		Test.checkTestTime(int h,String n,int h); 
	} 
} 

Student 쓰레드 클래스 (수정)

class Student extends Thread { 
	Professor prof;
	String name;
	int number; 
	long begin,end; 

 	Student(Professor p,String n,int no){ 
		prof = p;
		name = n; 
		number = no; 
	} 
	public void run() { 
		begin = System.currentTimeMillis(); // end가 없는 이유는 교수님이 시간 check 
		testJava(name,number); // n,no라고 매개변수 값을 주면 어떻게 되지? 
		prof.check_testpaper(this); // 교수 객체가 시험지를 check하는 것이니 prof.check~ 
		goHome(name,number);
	} 

	void testJava(String n,int no){ 
		System.out.println(no+"번"+n+"가 JAVA 시험을 보고있다"); 
		try {                         
			Thread.sleep((int)(Math.random()*1000)); } 
		catch(InterruptedException e) { } 
	} 
	void goHome(String n,int no){ 
		System.out.println(no+"번"+n+"가 집으로 돌아간다");
}
} 
  1. 시험 시간 currentTimeMillis()는 int형 변수가 아닌 long형 변수에 따로 begin,end를 정의해주어야 한다.
  2. Professor 클래스의 교수 객체를 따로 선언해주어야 한다. 애는 자료형 클래스가 아니라 내가 따로 만든 Professor 클래스의 교수 변수인 것이다.
  3. main 클래스에서 객체 생성 시에 정의되었던 교수 객체 공유, 이름, 학번을 생성자에서 받아와야 한다. 생성자는 생성자가 진행될때만 그 값이 살아있으므로 따로 멤버변수를 지정하여 그 값을 넣어주어야 한다.
  4. 쓰레드가 일을 하는 run() 클래스 안에는 쓰레드가 작업할 내용을 넣어준다. begin 변수 안에다가는 System으로부터 시험 시간을 받아와야 하므로 System 클래스 내의 time~ 메소드를 이용하여 학생이 시험 시작한 시간을 받아와야 한다. 나는 int형 변수에다가 그냥 time~ 메소드 값을 넣는 식으로 진행했는데 그러면 안된다.
  5. run() 메소드 안에다가는 쓰레드가 해야 할 작업들을 모두 명시해 주었지만, void testJava나 void goHome 메소드의 경우는 동기화 메소드가 아닌 학생 쓰레드 클래스 안에서도 충분히 작업할 수 있는 내용이므로 공유자원 클래스가 아닌 쓰레드 클래스에서 선언해주었다 > 만약에 이 내용을 공유자원 클래스에 선언하면?
  6. testJava 메소드 내에서 Math.random에서는 난수를 발생시키지만 0.0~1.0 내의 소수값을 반환한다. 그래서 1000을 곱하여 정수값으로 캐스트 형변환 해준다.
  7. testJava 내에서 sleep을 사용하였기 때문에, sleep() 상태에서 깨어나지 않을 수 있기 때문에 try~catch문으로 예외처리를 꼭 해주어야 한다. 나는 sleep을 여기서 사용할 줄 생각도 못했고 sleep()이 나오면 반드시 try~catch 예외처리를 해주어야 한다는 것도 간과하였다.

Professor 공유자원 클래스 (나)

class Test { // 공유자원 클래스 

void test(int h,String n){ 
	System.out.println(hakbun+"번"+name+"가 JAVA 시험을 보고있다"); 
} 
void goBackHome(int h,String n){ 
	System.out.println(hakbun+"번"+name+"가 집으로 돌아간다"); 
} 
synchronized void checkProfessor(int h,String n) { 
	System.out.println("안유정교수가"+hakbun+"번"+name+"의 시험지를 확인하고 접수했다"); 
	}
void checkTestTime(int h,String n,int h){ 
	if(time>700){
		time.sleep(1.0);
	}
	else { System.out.println(hakbun+"번"+name+"가 시험본 시간은"+time.random()); } 
}

Professor 공유자원 클래스 (수정)

class Professor { // 공유자원 교수 클래스 
	String name; 
	Professor(String n) { name = n; } 

	synchronized void check_testpaper(Student s) { 
		s.end = System.currentTimeMillis();
		System.out.println(s.number+"번"+s.name+"가 시험본 시간은"+(s.end-s.begin)+"ms");
		if((s.end-s.begin)<=700)
			System.out.println(name+"교수가"+s.number+"번"+s.name+"의 시험지를 확인하고 접수했다");
		else 
			System.out.println(s.number+"번"+s.name+"의 시험지는 time over"); 
	}
} 

1.나는 왜 공유자원 클래스를 Professor가 아닌 시험으로 생각을 했었을까? 지금 생각해보면 시험은 학생들이 동시에 보고 시험이 끝나는 순서대로 나가는 것인데, 왜 처음에 '시험'을 공유자원으로 생각했는지 의문이다. 교수는 한 사람인데 시험지 체크는 한 학생밖에 하지 못하므로 교수를 공유자원으로 설정해야 한다. (학생들에 대한 공유자원)
2. 공유자원 Professor 클래스 안에서 교수 객체가 해야 할 동기화 메소드만 따로 정의하였다. 나는 모든 메소드를 다 집어넣었다. (syn~ 키워드를 통해 동기화 메소드를 구분하긴 했다)
3. 시험시간이 700ms를 오버하면 교수 객체가 time over라고 출력을 해주므로 여기서 end 시간을 만들어주고, 시간이 700ms 판단하여야 한다.
s.name은 매개변수로 Student 클래스로부터 s로 해서 매개변수로 받아온다. 그래서 Student 클래스 내에 있는 (학생의) name인 것이다. 이런 식으로 접근을 해야 한다.
4. 시험지 제출을 하거나 time over이 되어 시험지 제출을 못하는 것은 교수 객체의 판단이다. 그래서 Student 객체의 s.end-s.begin 으로 해서 시험 시간을 판단한 뒤, if~else문을 활용하여 시간에 따른 시험지 제출 여부를 공유자원인 교수 클래스에서 설정해야 한다.

profile
컴퓨터공학과 학생 brandy 입니다. 개발+기획에 관심이 있지만, 개발 실력이 뛰어나진 않지만 성장하고자 하기 위해 벨로그를 작성합니다.

0개의 댓글