전에 메일로 질문 드렸던 시간, 이너클래스, 정적 네스티드 클래스, 스레드 질문과 답변 파일들 올려둘께요
// 질문
1번
시스템 시계는 현재 시각을 1970년 1월 1일 00:00:00 GMT를 기점으로 해서 현재까지 경과한 밀리세컨드 단위로 저장해서 관리합니다. (p.406에서 설명)
질문의 내용이 이것을 말하는 건지요
네 이거 맞습니다.
현재 시간이 2010년 10월 27일 수요일 오후 6시 30분 30초 일 경우 밀리세컨드 단위로 값을 어떻게 구하는지 좀 가르쳐주세요...
2번
611 페이지
package nestedclass_nestedinterface;
import java.util.ArrayList;
public class InnerClass
{
ArrayList- list = new ArrayList
- ();
void addItem(String name, int number, int price)
{
list.add(new Item(name, number, price)); // 이너클래스의 생성자 호출
}
void removeItem(int index)
{
list.remove(index);
}
int getItemNumber()
{
return list.size();
}
Item getItem(int index)
{
return list.get(index);
}
int getTotalPrice()
{
int total = 0;
for(Item item : list)
total += item.getPrice(); // 이너클래스 메서드 호출
return total;
}
void changeItemNumber(int index, int number)
{
Item item = list.get(index);
item.number = number; // 이너클래스 필드 사용
}
class Item // 상품 항목 클래스(이너클래스)
{
String name;
int number;
int price;
Item(String name, int number, int price)
{
this.name = name;
this.number = number;
this.price = price;
}
int getPrice()
{
return number * price;
}
}
}
package nestedclass_nestedinterface;
public class InnerClassMain
{
public static void main(String args[])
{
InnerClass inner = new InnerClass();
inner.addItem("쵸코렛", 3, 1000);
inner.addItem("케이크", 1, 25000);
inner.addItem("샴페인", 1, 7000);
printInnerClass(inner);
}
static void printInnerClass(InnerClass inner)
{
int number = inner.getItemNumber();
System.out.println(" 상품명 수량 단가 금액");
for(int cnt = 0; cnt < number; cnt++)
{
InnerClass.Item item = inner.getItem(cnt);
System.out.println("item = " + item);
/*
getItem(int index) 메서드 에서요 list.get(0) 값이 뭔지좀 가르쳐주세요...
cnt + 1 = 0 + 1 = 1
*/
System.out.printf("%3d %5s %5d %7d %7d %n", cnt + 1, item.name, item.number, item.price, item.getPrice());
}
System.out.printf(" 총계 %10d %n", inner.getTotalPrice());
}
}
3번
619 페이지
package nestedclass_nestedinterface;
public class StaticNestedClass
{
Point point1, point2;
StaticNestedClass(int x1, int y1, int x2, int y2)
{
point1 = new Point(x1, y1);
point2 = new Point(x2, y2); // 정적 네스티드 클래스 생성자 호출
}
void move(int offsetX, int offsetY)
{
point1.x += offsetX;
point1.y += offsetY;
point2.x += offsetX;
point2.y += offsetY; // 정적 네스티드 클래스 필드 사용
}
static class Point // 점 클래스(정적 네스티드 클래스)
{
int x, y;
Point(int x, int y)
{
this.x = x;
this.y = y;
}
}
}
package nestedclass_nestedinterface;
import nestedclass_nestedinterface.StaticNestedClass.Point;
public class StaticNestedClassMain
{
public static void main(String args[])
{
StaticNestedClass static1 = new StaticNestedClass(0, 0, 100, 100);
static1.move(10, 20);
printStaticNestedClass(static1.point1);
printStaticNestedClass(static1.point2);
}
static void printStaticNestedClass(StaticNestedClass.Point point)
{
System.out.printf("(%d, %d) %n", point.x, point.y);
}
}
// 실행결과
(10, 20)
(110, 120)
실행결과 이해가 안됩니다 설명좀 해주세요...
4번
688 페이지
package multithread_programming;
public class Alphabet2
{
public static void main(String args[])
{
Thread t = new SuzaThread2();
t.start(); // start() 메서드에 의해서 SuzaThread2 클래스에 run() 메서드 호출하면 숫자부터 출력되야 하는거 아닌가요 모든 실행이 알바벳부터 출력된거 같습 니다...
for(char c = A; c <= ; c++)
{
System.out.print(c);
try
{
Thread.sleep(1000);
}
catch(InterruptedException ie)
{
System.out.println(ie.getMessage());
}
}
}
}
package multithread_programming;
public class SuzaThread2 extends Thread
{
public void run()
{
for(int cnt = 0; cnt < 10; cnt++)
{
System.out.print(cnt);
try
{
Thread.sleep(1000);
}
catch(InterruptedException ie)
{
System.out.println(ie.getMessage());
}
}
}
}
// 실행결과들
A01B2C3DE45FG6H7I8J9KLMNOPQRSTUVWXYZ
A0B1C2D3E45FG6H7I89JKLMNOPQRSTUVWXYZ
A0B1C2D3E45FG6H7I8J9KLMNOPQRSTUVWXYZ
5번
package multithread_programming;
public class SharedArea9
{
double result;
boolean isready;
}
package multithread_programming;
public class PiCalculationThread5 extends Thread
{
SharedArea9 sharedarea;
public void run()
{
double total = 0.0;
for(int cnt = 1; cnt < 1000000000; cnt += 2)
if(cnt / 2 % 2 == 0)
total += 1.0 / cnt;
else
total -= 1.0 / cnt;
sharedarea.result = total * 4;
sharedarea.isready = true;
synchronized(sharedarea)
{
sharedarea.notify();
}
}
}
package multithread_programming;
public class PiPrintThread5 extends Thread
{
SharedArea9 sharedarea;
public void run()
{
if(sharedarea.isready != true)
{
synchronized(sharedarea)
{
try
{
sharedarea.wait();
}
catch(InterruptedException ie)
{
System.out.println(ie.getMessage());
}
}
}
System.out.println("sharedarea.result = " + sharedarea.result);
}
}
package multithread_programming;
public class MonitorRingThread extends Thread
{
Thread thread;
MonitorRingThread(Thread thread)
{
this.thread = thread;
}
public void run()
{
while(true)
{
Thread.State state = thread.getState();
System.out.println("스레드의 상태 = " + state);
if(state == Thread.State.TERMINATED)
break;
try
{
Thread.sleep(2000);
}
catch(InterruptedException ie)
{
ie.printStackTrace();
}
} // while 문장 = 모니터링 대상 스레드의 상태를 2초마다 한번씩 출력합니다.
}
}
package multithread_programming;
public class MultiThread11
{
public static void main(String args[])
{
PiCalculationThread5 thread1 = new PiCalculationThread5();
PiPrintThread5 thread2 = new PiPrintThread5();
// MonitorRingThread thread3 = new MonitorRingThread(thread1); // 모니터링 스레드 생성
MonitorRingThread thread3 = new MonitorRingThread(thread2); // 모니터링 스레드 생성
SharedArea9 sa = new SharedArea9();
thread1.sharedarea = sa;
thread2.sharedarea = sa;
thread1.start();
thread2.start();
thread3.start(); // 모니터링 스레드 시작
}
}
// 실행결과
스레드의 상태 = RUNNABLE
스레드의 상태 = RUNNABLE
스레드의 상태 = RUNNABLE
스레드의 상태 = RUNNABLE
스레드의 상태 = RUNNABLE
스레드의 상태 = RUNNABLE
스레드의 상태 = RUNNABLE
스레드의 상태 = RUNNABLE
스레드의 상태 = RUNNABLE
스레드의 상태 = RUNNABLE
스레드의 상태 = RUNNABLE
sharedarea.result = 3.141592651589258
스레드의 상태 = TERMINATED
스레드의 상태 = WAITING
스레드의 상태 = WAITING
스레드의 상태 = WAITING
스레드의 상태 = WAITING
스레드의 상태 = WAITING
스레드의 상태 = WAITING
스레드의 상태 = WAITING
스레드의 상태 = WAITING
스레드의 상태 = WAITING
스레드의 상태 = WAITING
스레드의 상태 = WAITING
sharedarea.result = 3.141592651589258
스레드의 상태 = TERMINATED
실행결과가 이렇게 나온 이유를 잘모르겠습니다 설명좀 해주세요 ...
==> 답변 부분
안녕하세요, 김윤명입니다.
답변이 늦어져서 죄송합니다.
(1번 답) 해당 시각을 포함한 GregorianCalendar 객체를 만든 다음에 그 객체에 대해 getTimeInMillis라는 메서드를 호출해서 구하면 됩니다.
이 메서드의 리턴 값은 long이므로 다음과 같이 long 타입의 변수에 받아야 합니다.
import java.util.GregorianCalendar;
class Test {
public static void main(String args[]) {
GregorianCalendar gc = new GregorianCalendar(2010, 9, 27, 18, 30, 30); // 책에서 설명했듯이 달은 0부터 시작하므로 9로 써야 함
long ms = gc.getTimeInMillis();
System.out.println(ms);
}
}
그리고 손으로 직접 계산하는 방법을 물으시는 거라면 경과한 날의 수를 먼저 계산하고 나서,
그 날의 수에 해당하는 밀리세컨트와 시,분,초에 해당하는 밀리세컨드를 고려해야 합니다.
그런데 이 때 주의 해야 할 점은 GMT와 우리나라의 표준시 간에 9시간의 시차가 있다는 점입니다.
그러므로 시각에서 9를 뺀 후에 계산을 해야 합니다.
구하는 밀리 세컨드 = 14909 * 24 * 3600 * 1000 + // 경과한 날에 해당하는 밀리세컨드 1970/1/1 부터 2010/9/26일까지 경과한 날수 = 14909
(18 - 9) * 3600 * 1000 + // 경과한 시에 해당하는 밀리세컨드
30 * 60 * 1000 + // 경과한 분에 해당하는 밀리세컨드
30 * 1000 ; // 경과한 초에 해당하는 밀리세컨드
위의 식을 계산하면 그 위의 프로그램에서 계산한 것과 마찬가지로 1288171830000라는 값이 나올 것입니다.
(2번답) List 객체에 add 메서드를 이용해서 데이터 항목을 추가하면 add 메서드를 호출한 순서대로 저장됩니다.
그러므로 list.get(0)의 리턴 값은 가장 처음 add 메서드를 호출할 때 넘겨준 Item("초코렛", 3, 100) 객체가 될 것입니다.
(3번답) 이 예제에 있는 StaticNestedClass는 수학에서 배우는 좌표계에서의 선분을 표현하고,
move 메서드는 그 선분을 파라미터로 넘겨준 (X값, Y값)만큼 평행 이동하는 일을 합니다.
그런데 이 예제에서는 처음에 (0, 0) 위치의 점과 (100, 100) 위치의 점을 연결하는 선분을 만들었고,
그 다음에 move 메서드를 호출해서 (10, 20)만큼 선분을 평행이동 시켰습니다.
그래서 그 결과로 선분의 위치는 (10, 20) 위치의 점과 (110, 120) 위치의 점을 연결하도록 이동되었습니다.
(4번답) start 메서드는 run 메서드를 직접 호출하는 것이 아니라 자바 가상 기계가 해당 스레드에게도 시간을 분배해 주도록 요구하는 역할을 합니다. 그러므로 start 메서드를 호출했더라도 그 스레드의 차례가 아직 돌아오지 않았으면 run 메서드 내에 있는 코드가 아직 실행되지 않을 수도 있습니다.
(5번답) 이 예제에서는 모니터 스레드와 함께 2개의 스레드가 동시에 실행하도록 되어 있지만, 실제로 파이를 출력하는 스레드가 하는 일은 파이 값이 계산될 때까지 기다리는 것이 대부분입니다. 그렇기 때문에 모니터링을 하는 동안 파이을 계산하는 스레드는 아주 바쁘게 CPU를 사용하면서 계산을 하고 있기 때문에 RUNNABLE 상태로 나오지만, 파이를 출력하는 스레드는 wait 메서드를 호출해놓고 기다리는 상태로 있는 시간이 대부분이기 때문에 계속 WATING 상태로 나오는 것입니다.
원하시는 답변이 개념적인 설명인지, 프로그램의 작동 방법에 대한 보충 설명인지 잘 파악이 안되는 부분은 제가 짐작하는 대로 답변을 했습니다.
모두 원하는 답변이 되었는지 모르겠습니다. 궁금한 점 있으시면 다시 질문 주시기 바랍니다.
감사합니다.
김윤명