Category: Java

12.マルチスレッド

12章 マルチスレッド
1.スレッドとは
 一つのプロセスで、同時に複数の処理をすることができる。例えば、ブラウザでインターネットからファイルを取得する仕事が動き、さらにユーザからの操作を受け付ける仕事があり・・・これらが同時に動いている。この仕事一つ一つをスレッドという。
複数スレッドが同時に処理することができるプログラムをマルチスレッドプログラムという。
2.スレッドのライフサイクル
 同時にスレッドが動くといっても実際はCPUが一つなので、一つ目のスレッドが動いたら二つ目のスレッドが動く、というように短時間の間に交互に動く。これをタイムディビジョン方式という。
実行状態
現在、実行されているスレッド
待機状態
通信の返事が返ってくるまで待つなどキーボード入力を待ったり、イベントが終了するまで待機している状態。または、何もすることがない状態。
実行可能状態

 本来は、すぐに実行になりたいが別のスレッドが実行中の場合は、一時待つ。
3.スレッドの作成 〜Threadクラス〜
 スレッドを作るには、java.langパッケージのThredクラスを継承すれば作られる。さらに、スレッドの中身はrunメソッドをオーバーライドして記述する。そして、スレッドクラスのstartメソッドを呼び起こせば、新しいスレッドが作成されrunメソッドが別スレッドとして実行される。
Test.java// 独自のスレッドクラス
class MyThread extends Thread{
public  MyThread( ){
}
// このrunメソッドがスレッド本体
public void run( ){
System.out.println(“MyThread Start!”);

// 10回500ミリ秒毎n”Hello”と表示する
    for (int i = 0 ; i < 10 ; i++ ) {
System.out println(“Hello”);
      try{
// sleepメソッドはThreadクラスの静的メソッドでnミリ秒(この場合500ミリ秒)待つ(待機状態)メソッド。
// 例外を投げる可能性があるので、キャッチしないとならない。
Thread.sleep(500);
}catch(Exception e){ }
}
}

public class Test {
public static void main (String args [ ] ) {
// 独自のスレッドクラスのインスタンスを作成
MyThread t = new MyThread(“Thread1”);

// スレッドを開始
t.start( ) ;

// 1秒毎に”Hi !”と10回表示する
for( int i = 0 ; i < 10 ; i++ ) {
System.out.println(“Hi !”) ;
try{
Thread.sleep(1000);
}catch(Exception e){ }
}
}
}

C:\java>javac Test.java

C:\java>java Test
Hi!
MyThread Start!
Hello
Hello
Hi!
Hello
Hello
Hi!
Hello
Hello
Hi!
Hello
Hello
Hi!
MyThread End!
Hi!
Hi!
Hi!
Hi!
C:\java>

4.Threadクラスのメソッド
●コンストラクタ概要
Thread( )
 新しいThreadオブジェクトを割り当てる
Thread(Runnable target )
 新しいThreadオブジェクトを割り当てる
Thread(Runnable target,String name)
 nameという名前の新しいThreadオブジェクトを割り当てる
Thread(String name)
 nameという名前の新しいThreadオブジェクトを割り当てる
●メソッド概要
String
getName( )        
 このスレッドの名前を返す 
boolean     
isAlive( )        
このスレッドが生存しているかどうかを判定する 
void          
join(long millis)  
 このスレッドが終了するのを、最高でmillisミリ秒待機する
void          
run( )                 
このスレッドが別個のRunnable実行オブジェクトを使用して作成された場合、そのRunnableオブジェクトのrunメソッドが呼び出される 
void
setName(String name)
このスレッドを、デーモンスレッドまたはユーザスレッドとしてマークする 
void
setPriority(int newPriority)
このスレッドの優先順位を変更する 
static void
sleep(long millis)
現在実行中のスレッドを指定されたミリ秒数の間、スリープ(一時的に実行を停止)させる
void
start( )
このスレッドの実行を開始 
static void
yield( )
現在実行中のスレッドオブジェクトを一時的に休止させ、ほかのスレッドが実行できるようにする 
5.スレッドの作成 〜Runnableインターフェース〜
Test.java// 独自のクラス
class MyRunnable implements Runnable{
// このrunメソッドがスレッド本体
public void run( ){
System.out.println(“MyRunnable Start!”);

// 10回500ミリ秒毎n”Hello”と表示する
    for (int i = 0 ; i < 10 ; i++ ) {
System.out println(“Hello”);
      try{
// sleepメソッドはThreadクラスの静的メソッドでnミリ秒(この場合500ミリ秒)待つ(待機状態)メソッド。
// 例外を投げる可能性があるので、キャッチしないとならない。
Thread.sleep(500);
}catch(Exception e){ }
}
}

public class Test {
public static void main (String args [ ] ) {
// 独自のスレッドクラスのインスタンスを作成
Runnable r = new MyRunnable( ):
Thread t = new Thread(r);

// スレッドを開始
t.start( ) ;

// 1秒毎に”Hi !”と10回表示する
for( int i = 0 ; i < 10 ; i++ ) {
System.out.println(“Hi !”) ;
try{
Thread.sleep(1000);
}catch(Exception e){ }
}
}
}

C:\java>javac Test.java

C:\java>java Test
Hi!
MyRunnable Start
Hello
Hello
Hi!
Hello
Hello
Hi!
Hello
Hello
Hi!
Hello
Hello
Hi!
MyRunnable End!
Hi!
Hi!
Hi!
Hi!
C:\java>

6.同期
 ロックとは、一つ目のスレッドがあるメソッドをロックすると別のスレッドはそのメソッド内に入れなくなる。そのメソッドを出るときにロックを解除することで別スレッドがそのメソッドに入ることができるようにする。
メソッドを作成するときに「Synchronized」修飾子をつける。javaではこれだけでロックをかける(同期をとる)ことができる。
Test.java// 口座クラス
class Account{
private int balance = 0;

 

 synchronized void deposit ( int amount ){
int a = balance;
    a = a + amount;
    try{
Thread.sleep((int)(Math.random( )*10));
}catch(Exception e){ }
    balance = a;
}
        int getBalance( ){
}
}

// 顧客クラス
class Customer extends Thread{
     Account account;

// コンストラクタ
  Customer(Account account){
this.account = account;
}

// 10円ずつ貯金することを1000回繰り返す
public void run( ) {
          for( int i = 0 ; i < 1000 ; i++ ){
account.deposit(10);
}
}
}

class Test{
public static void main(String args[ ]){
     // 口座を作る
Account account = new Account( );

        // 10人の顧客を作る
Customer customers[ ] = new Customer[10];

        // 10人の顧客が一つの口座に振り込み処理を
   //開始す
for( int i = 0 ; i < 10 ; i++ ){
customer[i] = new Customer(account);
customer[i].start( );

}

        // 10人のスレッドが終わるのを待つ
try{
for( int i = 0 ; < 10 ; i++ ){
customers[i].join( );
}
}catch(Exception e){
System.err.println(“Error:”+e);
}

     // 残高表示
System.out.println(“残高:”+account.getBalance()));
}
}

Test.java// 口座クラス
class Account{
private int balance = 0;

void deposit ( int amount ){
int a = balance;
    a = a + amount;
    try{
Thread.sleep((int)(Math.random( )*10));
}catch(Exception e){ }
    balance = a;
}

        int getBalance( ){
}
}

// 顧客クラス
class Customer extends Thread{
     Account account;

// コンストラクタ
  Customer(Account account){
this.account = account;
}

// 10円ずつ貯金することを1000回繰り返す
public void run( ) {
          for( int i = 0 ; i < 1000 ; i++ ){
account.deposit(10);
}
}
}

class Test{
public static void main(String args[ ]){
     // 口座を作る
Account account = new Account( );

        // 10人の顧客を作る
Customer customers[ ] = new Customer[10];

        // 10人の顧客が一つの口座に振り込み処理を
   //開始する
for( int i = 0 ; i < 10 ; i++ ){
customer[i] = new Customer(account);
customer[i].start( );

}

        // 10人のスレッドが終わるのを待つ
try{
for( int i = 0 ; < 10 ; i++ ){
customers[i].join( );
}
}catch(Exception e){
System.err.println(“Error:”+e);
}

     // 残高表示
System.out.println(“残高:”+account.getBalance()));
}
}

C:\java>javac Test.java

C:\java>java Test
残高:100000C:\java>

C:\java>javac Test.java

C:\java>java Test
残高:10000C:\java>

メソッドにsynchronized修飾子をつけて同期をとる方法ではなく、オブジェクトにロックをかけて同期をとる方法
Test.java// 口座クラス
class Account{
private int balance = 0;

void deposit ( int amount ){
int a = balance;
    a = a + amount;
    try{
Thread.sleep((int)(Math.random( )*10));
}catch(Exception e){ }
    balance = a;
}

        int getBalance( ){
}
}

// 顧客クラス
class Customer extends Thread{
     Account account;

// コンストラクタ
  Customer(Account account){
this.account = account;
}

// 10円ずつ貯金することを1000回繰り返す
public void run( ) {
          for( int i = 0 ; i < 1000 ; i++ ){
sychronized( account ){
account.deposit(10);
}
}
}
}

class Test{
public static void main(String args[ ]){
     // 口座を作る
Account account = new Account( );

        // 10人の顧客を作る
Customer customers[ ] = new Customer[10];

        // 10人の顧客が一つの口座に振り込み処理を開始する
for( int i = 0 ; i < 10 ; i++ ){
customer[i] = new Customer(account);
customer[i].start( );

}

        // 10人のスレッドが終わるのを待つ
try{
for( int i = 0 ; < 10 ; i++ ){
customers[i].join( );
}
}catch(Exception e){
System.err.println(“Error:”+e);
}

     // 残高表示
System.out.println(“残高:”+account.getBalance()));
}
}

C:\java>javac Test.javaC:\java>java Test
残高:100000

C:\java>

 この方法は、accountにロックをかけている。一つ目のスレッドがaccountにロックをかけると、別のスレッドはロックが解除されるまで、synchronizedで囲まれたブロック(synchronizedブロック)には、入ることができない。
7.デットロック
 デットロックとは、マルチスレッドプログラミングで起こりやすいバグの一つ。一つ目のスレッドがXというオブジェクトのロックが解除されるのを待つ。二つ目のスレッドはYというオブジェクトをロックしており、Xというオブジェクトの解放を待つ。このような場合、両方のスレッドはオブジェクトの解放を永遠に待ち続けてしまうため、プログラムは進まなくなり、いわゆる暴走の状態に陥る。このように、複数のスレッドがお互いにロックの解放を永久に待ち続けてしまうことをデットロックという。
Test.java class X{
  int x;
}

class Y{
int y;
}

class A extends Thread{
X x;
Y y;

A(X x, Y y){
this.x = x;
this.y = y;
}

void func1( ){
     System.out.println(“func1:start”);
synchronized(x){
synchronized(y){
try{
sleep(10);
}catch(Exception e){ }
}
}
}

void func2( ) {
System.out println(“func2:start”);
synchronized(y){
synchronized(x){
try{
sleep(10);
}catch(Exception e){ }
}
}
}

public void run( ){
for ( int i = 0 ; i < 1000 ; i++ ){
func1( );
func2( );
}
}
}

class Test{
pubic static void main ( String args[ ]) {
X x = new X( );
Y y = new Y( );

A a[ ] = new A[10];
   for( int i = 0 ; < 10 ; i++ ) {
try{
                 a[i].join( );
}catch(Exception e){ }
}
}
}

C:\java>javac Test.javaC:\java>java Test
func1:start
func1:start
func1:start
func1:start
func1:start
func1:start
func1:start
func1:start
func2:start
func1:start
func1:start
func2:start       ←ここでデットロックが発生

 

 多くの場合、ロックするオブジェクトを同じ順番でロックすれば、デットロックは防げる。例えば上記では、func2のsychronizedでロックする順番をfunc1と同じように「x→y」の順番でロックすればデットロックは防げる。言い換えるとオブジェクトに優先順位を与えるということになる。
このようにマルチスレッド特有のバグが発生した場合の多くは、バグを再現させることすら難しく、デバッグ作業は大変な作業になってしまう。バグが起きないようにあらかじめちゃんと設計してからプログラミングする必要がある。
8.スレッド間の通信
 スレッドから一時的にロックを解放し、他のスレッドにsynchronizedメソッドもしくはsynchronizedブロックを実行するチャンスを与えることができる。例えば、一つ目のスレッドはメッセージを受信するスレッドで、二つ目のスレッドはメッセージを与えるスレッドである。メッセージ受信のスレッドは、メッセージボックスにメッセージがなければメッセージが格納されるまですることがない。このような場合ほかのスレッド(メッセージ送信スレッド)に制御を移す。逆にメッセージ送信スレッドは、メッセージボックスがいっぱいならば、メッセージ受信スレッドがメッセージを処理し終わるまで待たなければならない。
このように、他のスレッドが処理し終わるまで待つ場合は「wait」メソッドを使用し、他のスレッドに制御を与える場合は「notify」または「notifyAll」メソッドを使用する。notifyAllメソッドはwaitしているすべてのメソッドに対して通知をするが、notifyメソッドは、いずれか一つのスレッドに対してのみ通知する。どのスレッドに通知されるかは、JVMが勝手に決めていいことになっている。
Test.java import java.util.*;

// メッセージボックス
class MessageBox{
     private String message;

// メッセージボックスにメッセージを入れる
synchronized void  messageIn(String msg){
try{
// メッセージがすでに入っていれば、なくなるまで待つ
while( message != null){
wait( );
}

// メッセージを入れる
message = msg;

// メッセージを入れ終わったら別のスレッドを起こす
notifyAll( );

// 以下例外処理
}catch(Exception e){
System.err.println(“messageIn:Error:”+e);
System.exit(1);
}
}

// メッセージ取り出し
synchronized String messageOut( ){
try {
// メッセージがなければ、メッセージが入るまで待つ
while(message == null){
wait( );
}

// メッセージ取り出し
String s == message;
message = null ;

// 取り出したら別のスレッドを起こす
notifyAll( );
return s ;
// 以下例外処理
} catch (Exception e ){ }
System.err.println(“messageOut:Error”);
System.exit( 1);
return “”;
}
}

// 以下例外処理
class MessageSender extends Thread{
public void run( ){
for( int i = 0 ; i < 100 ; i++ ){
Test.msgBox.messageIn(“”+Math.random( ));
          }
}
}

// メッセージを取り出し、表示するスレッド
class MessageReciever extends Thread {
public void run ( ){
          for ( int i = 0 ; i < 100 ; i++ ){
System.out.println(Test.msgBox.messageOut( ));
}
}
}

class Test{
public static MessageBox msgBox = new MessageBox( );

public static  void main(String args[ ]){
MessageReciever reciever = new MessageReciever( );
reciever.start( );

MessageSender sender = new MessageSender( );
sender.start( );

try{
sender.join( ;
reciever.join( );
}catch(Exception e){ }
}
}

C:\java>javac Test.javaC:\java>java Test
0.2894081823761079
0.20714542091971344

中略

0.519766868805261
0.6181891980702379

C:\java>

  

14-22.Calendar

 
 
 

22.Calendar
 Calendarは、DateオブジェクトとYEAR、MONTH、DAY、HOURなどの整数フィールドの間で変換を行うための抽象クラス。実際には具象クラスであるGregorianCalendarを使用する。

import java.util.Calendar

コンストラクタ
Date()
現在の日付と時刻で初期化されたDateインスタンスを作成。
Date(long msec)
グリニッジ標準時1970年1月1日0時からmsecミリ秒経過したDateインスタンスを作成。
メンバー変数
static int YEAR
getおよびsetのための、年を示すフィールド値。
static int MONTH
getおよびsetのための、月を示すフィールド値。
static int DATE
getおよびsetのための、日を示すフィールド値。
static int DAY_OF_MONTH
getおよびsetのための、日を示すフィールド値。
static int DAY_OF_WEEK
getおよびsetのための、曜日を示すフィールド値。
static int DAY_OF_YEAR
getおよびsetのための、1/1から数えて何日目かを示す。
static int WEEK_OF_MONTH
getおよびsetのためのフィールド値で、現在の月の何週目かを示す。
static int WEEK_OF_YEAR
getおよびsetのためのフィールド値で、現在の年の何週目かを示す。
static int DAY
getおよびsetのための、日を示すフィールド値。
static int HOUR
getおよびsetのための、何時かを示す。(最大は12)
static int HOUR_OF_DAY
getおよびsetのための、何時かを示す。(最大は24)
static int MINUTE
getおよびsetのための、分を示すフィールド値。
static int SECOND
getおよびsetのための、秒を示すフィールド値。
static int MILISECOND
getおよびsetのための、ミリ秒を示すフィールド値。(Windowsでは10ミリ秒単位)
static int AM
午前を表す定数
static int PM
午前を表す定数
static int AM_PM
午前を表す定数
static int SUNDAY
日曜日を示すDAY_OF_WEEKフィールドの値。
static int MONDAY
月曜日を示すDAY_OF_WEEKフィールドの値。
static int TUESDAY
火曜日を示すDAY_OF_WEEKフィールドの値。
static int WEDNESDAY
水曜日を示すDAY_OF_WEEKフィールドの値。
static int THURSDAY
木曜日を示すDAY_OF_WEEKフィールドの値。
static int FRIDAY
金曜日を示すDAY_OF_WEEKフィールドの値。
static int SATURDAY
土曜日を示すDAY_OF_WEEKフィールドの値。
static int JANUARY
1月を示すMONTHフィールドの値。
実際の値は0となっています。
static int FEBRUARY
2月を示すMONTHフィールドの値。
実際の値は1となっている。
static int MARCH
3月を示すMONTHフィールドの値。
実際の値は2となっている。
static int APRIL
4月を示すMONTHフィールドの値。
実際の値は3となっている。
static int MAY
5月を示すMONTHフィールドの値。
実際の値は4となっている。
static int JUNE
6月を示すMONTHフィールドの値。
実際の値は5となっている。
static int JULY
7月を示すMONTHフィールドの値。
実際の値は6となっている。
static int AUGUST
8月を示すMONTHフィールドの値。
実際の値は7となっている。
static int SEPTEMBER
9月を示すMONTHフィールドの値。
実際の値は8となっている。
static int OCTORBER
10月を示すMONTHフィールドの値。
実際の値は9となっている。
static int NOVEMBER
11月を示すMONTHフィールドの値。
実際の値は10となっている。
static int DECEMBER
12月を示すMONTHフィールドの値。
実際の値は11となっている。
static int UNDECIMBER
13月を示すMONTHフィールドの値。
実際の値は12となっている。
(太陽暦では使用しない、太陰暦で使用。)
static int DST_OFFSET
getおよびsetのためのフィールド値で、夏時間のオフセットをミリ秒単位で示す。
static int ERA
getおよびsetのためのフィールド値で、ユリウス暦のADまたはBCなどの年代を示す。

 
 

コンストラクタ
Calendar()
デフォルトのタイムゾーンおよびロケールを使用してCalendarインスタンスを作成。
メソッド
Calendar getInstance()
デフォルトのタイムゾーンおよびロケールを使用してCalendarインスタンスを作成。
Date getTime()
インスタンスの持つの時刻を返す。
int get(int field)
fieldで示されるフィールドの値を返します。
例えば、Calendarインスタンスcalが示す時間は24時間制で何時になるかは
cal.get(Calendar.HOUR_OF_DAY)
とする。
long getTimeInMillis()
現在のインスタンスを1970年1月1日0時0分0秒からのミリ秒で取得する。
void set(int field, int value)
filedで示されるフィールド値を設定します。
例えば、Calendarインスタンスcalが示す時間は24時間制で13時にする場合は
cal.set(Calendar.HOUR_OF_DAY, 13)
とする。
void set(int year, int month, int day)
year年month月day日に設定します。時間などその他のフィールドは保持される。
例えば、2004年8月31日に設定する場合は、
cal.set(2004,Calendar.AUGUST, 31) または
ca.set(2004, 8-1, 31)
とする。
void set(int year, int month, int day, int hour, int minute)
year年month月day日hour時minute分に設定する。秒などその他のフィールドは保持される。
例えば、2004年8月31日10時30分に設定する場合は、
cal.set(2004,Calendar.AUGUST, 31, 10, 30) または
ca.set(2004, 8-1, 31, 10, 30)
とする。
void set(int year, int month, int day, int hour, int minute, int second)
year年month月day日hour時minute分second秒に設定します。その他のフィールドは保持される。
例えば、2004年8月31日10時30分10秒に設定する場合は、
cal.set(2004,Calendar.AUGUST, 31, 10, 30, 10) または
ca.set(2004, 8-1, 31, 10, 30, 10)
とする。
void setTime(Date time)
時刻timeを設定。
void setTimeInMillis(long l)
現在のインスタンスを1970年1月1日0時0分0秒からのミリ秒で設定。
void clear()
すべてのフィールドがクリアされます。日時は1970年1月1日0時0分0秒になる。
void clear(int field)
fieldで示されるフィールドがクリアされる。
void add(int field, int amount)
fieldをamoutだけ加算します。
現在のCalndarインスタンスcalの30日前を求めるには
cal.add(Calendar.DATE, -30)
とする。
void roll(int field, boolean up)
upがtrueの場合はfieldで示されるフィールドを1だけ加算。
upがfalseの場合はfieldで示されるフィールドを1だけ減算。
ただし、上のフィールドは変更しません。
例えば、8月31日の場合、DATEフィールドをupさせた場合は、8月1日となる。
boolean equals(Object obj)
objがCalendarクラスもしくはそのサブクラスで、同じ値を持つ場合はtrueを、それ以外はfalseを返す。
boolean after(Object obj)
objがCalendarクラスもしくはそのサブクラスで、自分自身の方が後ならばtrueを返す。
boolean before(Object obj)
objがCalendarクラスもしくはそのサブクラスで、自分自身の方が前ならばtrueを返す。
int getFirstDayOfWeek()
週の最初が何曜日かを返す。
例えば日本やアメリカではSUNDAY(1)が、フランスではMONDAY(2)が返される。
int getMinimum(int field)
fieldで示されたフィールドの最小値を示す。
たとえば、グレゴリオ暦のDAY_OF_MONTHは1。
int getMaximum(int field)
fieldで示されたフィールドの最大値示します。
たとえば、グレゴリオ暦のDAY_OF_MONTHは31。
int getGreatestMinimum(int field)
fieldで示されたフィールドの最小値が変化する場合、その最大値を取得する。
たとえば、グレゴリオ暦のDAY_OF_MONTHは1。
int getLeastMaximum(int field)
fieldで示されたフィールドの最大値が変化する場合、その最小値を取得する。
たとえば、グレゴリオ暦のDAY_OF_MONTHは28。
String toString()
現在のインスタンスを文字列に変換します。
コンパイラなどによって異なるのでデバッグ以外には使用しない。

 
 

GregorianCalendar

import java.util.GregorianCalendar

GregorianCalendarは、Calendarクラスの具象クラス。日本を含め、世界のほとんどの国で採用されている太陽暦のカレンダー。ほとんどのメソッドは、Calendarクラスから受け継がれたものを利用。
GregorianCalendarのメンバー変数
int AD
キリスト紀元 (西暦) を示す ERA フィールドの値。
int BC
キリスト紀元 (BC) より前の期間を示す ERA フィールドの値。
GregorianCalendarのコンストラクタ
GregorianCalendar()
デフォルトのタイムゾーンおよびロケールを使用してGregorianCalendarインスタンスを作成。
GregorianCalendar(int year, int month, int date)
デフォルトのタイムゾーンおよびロケールを使用して、指定した年月日でGregorianCalendarインスタンスを作成。
GregorianCalendar(int year, int month, int date, int hour, int minute)
デフォルトのタイムゾーンおよびロケールを使用して、指定した日時でGregorianCalendarインスタンスを作成。
GregorianCalendar(int year, int month, int date, int hour, int minute, int second)
デフォルトのタイムゾーンおよびロケールを使用して、指定した日時でGregorianCalendarインスタンスを作成。
GregorianCalendarのメソッド
boolean isLeapYear(int year)
year年が閏年ならtrueを返す。

14-21.Date

 
 
 

21.Date
 Dateクラスは日付と時間に関する情報を扱う。

import java.util.Date

コンストラクタ
Date()
      現在の日付と時刻で初期化されたDateインスタンスを作成。
Date(long msec)
      グリニッジ標準時1970年1月1日0時からmsecミリ秒経過したDateインスタンスを作成。
 
メソッド
boolean after(Date d)
      dがこのオブジェクトよりも後にある場合にtrueを返す。
boolean before(Date d)
      dがこのオブジェクトよりも前にある場合にtrueを返す。
static
boolean
equals(Date d)
      dがこのオブジェクトと等しい場合にtrueを返します。
static
boolean
isDigit(char ch)
      chが数字かを調べます。定義されていればtrueが返される。
      全角半角は問わない。
long getTime()
      このオブジェクトがグリニッジ標準時1970年1月1日0時からどのくらい経過しているかを返す。単位はミリ秒です。
void setTime(long msec)
      グリニッジ標準時1970年1月1日0時からmsecミリ秒経過した日付と時間に設定する。
String toString()
      日付を文字列に変換して返す。