프로그래밍/JAVA 자바

스레드(3) Timer 클래스 / wait

Heidong 2021. 9. 7. 00:01
반응형
package threadEx2;

import java.util.Calendar;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;

public class Ex001_Timer {

	public static void main(String[] args) {
		new MyTimer();
	}
}

class MyTimer {
	public MyTimer() {
		// TimerTask : 타이머에 의해 1회 또는 반복 실행하도록 태스크되는 스케줄
		TimerTask task = new TimerTask() {
			@Override
			public void run() {
				printTimes();
			}
		};
		
		// Timer : 스케줄
		//  단점 : 시간이 지연 될 수 있다.(0.001 ~ 0.002 초)
		Timer t = new Timer();
		// t.schedule(task, 1000); // 1초후 한번 실행
		// t.schedule(task, 2000, 1000); // 2초후 1초 마다 무한 반복
		t.schedule(task, new Date(System.currentTimeMillis()), 1000); // 바로 실행하며 1초마다 무한 반복
		
		// t.cancel(); // 타이머 종료
	}
	
	private void printTimes() {
		Calendar cal = Calendar.getInstance();
		
		String s = String.format("%tF %tT", cal, cal);
		System.out.println(s);
	}
}

- TimerTask = 타이머에 의해서 1회 또는 반복 실행 하도록 테스크 되는 스케줄

- Timer = 스케쥴

- .schedule(task, , )를 사용해서 간격을 조절 할 수 있다.

 

(t는 Timer 객체 생성한거임)

t.schedule(task, 1000); // 1초후 한번 실행

t.schedule(task, 2000, 1000); // 2초후 1초 마다 무한 반복

t.schedule(task, new Date(System.currentTimeMillis()), 1000); // 바로 실행하며 1초마다 무한 반복

 

package threadEx2;

import java.util.Calendar;
import java.util.Timer;
import java.util.TimerTask;

public class Ex002_Timer {
	public static void main(String[] args) {
		MyScheduler t = new MyScheduler();
		t.start();
	}
}

class MyScheduler extends Thread {
	private long num = 0;
	
	public MyScheduler() {
		TimerTask task = new TimerTask() {
			@Override
			public void run() {
				num = 0;
			}
		};
		
/*		
		Timer t = new Timer();
		Calendar cal = Calendar.getInstance();
		t.schedule(task, cal.getTime(), 10000); // 바로 실행하며, 10초 마다 반복 실행
*/
		
		// 다음날 0시 0분 0초에 시작하여 하루에 한번씩 반복
		Timer t = new Timer();
		Calendar cal = Calendar.getInstance();
		cal.add(Calendar.DATE, 1);
		cal.set(Calendar.HOUR_OF_DAY, 0);
		cal.set(Calendar.MINUTE, 0);
		cal.set(Calendar.SECOND, 0);
		cal.set(Calendar.MILLISECOND, 0);
		t.schedule( task, cal.getTime(), 1000*60*60*24 );
		
	}
	
	public void run() {
		while(true) {
			try {
				System.out.println("num : " + (++num));
				sleep(1000);
			} catch (Exception e) {
			}
		}
	}
}

- num을 1초마다 증가시킴

- 다음날 0시 0분 0초에 시작하여 하루에 한번씩 반복

 

 

Wait

package threadEx2;

public class Ex005_wait {
	public static void main(String[] args) {
		MyBank3 atm = new MyBank3();
		
		Thread t1 = new Thread(atm, "t1");
		Thread t2 = new Thread(atm, "t2");
		
		t1.start();
		t2.start();
	}
}

class MyBank3 implements Runnable {
	private long money = 10000;
	
	public void run() {
		synchronized (this) {
			for(int i = 0; i < 10; i++) {
				if(getMoney() <= 0) {
					// wait()에 의해 대기하고 있는 모든 스레드를 깨운다.
					this.notifyAll();
					break;
				}
				
				drawMoney(1000);
				
				if(getMoney()>=2000 && getMoney() % 2000 == 0) {
					try {
						// wait()를 만나면 해당 쓰레드는 해당 객체의 모니터링 락에 대한 권한을 가지고 있으면
						//  모니터링 락의 권한을 놓고 대기한다.
						// synchronized 블록에서만 사용
						this.wait();
					} catch (Exception e) {
					}
				} else {
					// wait()에 의해 대기하고 있는 해당 스레드를 깨운다.
					// 아래 notify()를 주석 처리하면 무한 대기(deadlook) 상태가 된다.
					this.notify();
				}
				
			}
		}
	}
	
	public long getMoney() {
		return money;
	}
	
	public void drawMoney(long m) {
		System.out.print(Thread.currentThread().getName()+", "); // 현재 스레드명 출력
		
		if(getMoney() >= m) {
			money -= m;
			System.out.printf("잔액 : %,d원\n", getMoney());
		} else {
			System.out.println("잔액이 부족 합니다.");
		}
	}
	
}

wait과 notify는 동기화된 스레드에서만 사용이 가능하다.

 

- 간단하게 wait을 만나면 대기함

- notify하면 깨움

- notifyAll하면 모든 잠들어 있는 스레드를 깨움

 

반응형