organize/자바

Java 34

001cloudid 2024. 8. 22. 11:14
728x90

sleep()

  • 현재 쓰레드(자기 자신, static)를 지정된 시간동안 멈추게 함.
static void sleep(long millis[, int nanos]) //천분의 일초(+나노초) 단위
  • 예외처리를 해야함(InterruptedException(Exception의 자손)이 발생하면 깨어남)
try{
	Thread.sleep(1000); //쓰레드를 1초동안 멈추게 함
} catch(InterruptedException e){}

//항상 try-catch를 하기 번거로움 
//=>
void delay(long millis){
	try{
    	Thread.sleep(millis);
    } catch(InterruptedException e){}
}
  • 특정 쓰레드를 지정해서 멈추게 하는 것은 불가능함
try{
	th1.sleep(1000);
} catch(InterruptedException e){}

=>

try{
	Thread.sleep(1000); //클래스 이름(static 메소드)
} catch(InterruptedException e){}
package chapter13;

class 쓰레드6_1a extends Thread{
	public void run() {
		for(int i = 0; i < 300; i++) System.out.print("-");
		System.out.println("<<th1>>종료");
	}
}
class 쓰레드6_1b extends Thread{
	public void run() {
		for(int i = 0; i < 300; i++) System.out.print("|");
		System.out.println("[[th2]]종료");
	}
}
public class 쓰레드6_1 {

	public static void main(String[] args) {

		쓰레드6_1a th1 = new  쓰레드6_1a();
		쓰레드6_1b th2 = new  쓰레드6_1b();
		
		th1.start();
		th2.start();
		
//		try {
////			th1.sleep(2000); //th1이 잠자는 것이 아닌 main 쓰레드가 잠자기
//			Thread.sleep(2000);
//		} catch (InterruptedException e) {
//		}
		delay(2000);
		
		System.out.println("((main))종료");
		
	}
	
	static void delay(long millis) {
	try {
//		th1.sleep(2000); //th1이 잠자는 것이 아닌 main 쓰레드가 잠자기
		Thread.sleep(2000);
	} catch (InterruptedException e) {
	}
}	


}

 

interrupt()

  • 대기상태(WAITING)인(작업이 중단된) 쓰레드를 실행대기 상태(RUNNABLE)로 만듦
void interrupt() //쓰레드의 interrupted상태를 false에서 true로 변경
boolean isInterrupted() //쓰레드의 interrupted상태를 반환
static boolean interrupted() //현재 쓰레드의 interrupted상태를 알려주고, false로 초기화
package chapter13;

import javax.swing.JOptionPane;

class Thread6_2 extends Thread{
	public void run() {
		int i = 10;
		
		while(i!=0 && !isInterrupted()) {
			System.out.println(i--);
			for(long x=0;x<250000000000L;x++); //시간지연
		}
		System.out.println("카운트가 종료됨");
		
		System.out.println("th1의 isInterrupted() : " + this.isInterrupted());
		System.out.println("th1의 interrupted() : " + Thread.interrupted()); //isInterrupted()와 달리 interrupted()는 interrupted라는 상태변수를 false로 초기화 
		System.out.println("th1의 interrupted() : " + Thread.interrupted());  
	}
}

public class 쓰레드6_2 {

	public static void main(String[] args) {

		Thread6_2 th1 = new Thread6_2();
		th1.start();
		
		System.out.println("isInterrupted() : " + th1.isInterrupted());
		String input = JOptionPane.showInputDialog("아무 값이나 입력");
		System.out.println("입력한 값은 " + input);
		th1.interrupt(); //interrupt()를 호출하면 interrupted상태가 true가 됨
		System.out.println("isInterrupted() : " + th1.isInterrupted());
		System.out.println("main 쓰레드의 interrupted() : " + Thread.interrupted()); //main쓰레드가 interrupt되었는지 확인
	}

}

 

suspend(), resume(), stop()

  • 쓰레드의 실행을 일시정지시킴
  • 쓰레드의 실행을 재개시킴
  • 쓰레드의 실행을 완전정지시킴
void suspend() //쓰레드를 일시정지 시킴
void resume() //suspend()에 의해 일시정지된 쓰레드를 실행대기상태로 만듦
void stop() //쓰레드를 즉시 종료시킴
  • suspend(), resume(), stop()은 교착상태에 빠지기 쉬워 deprecated됨.
    사용을 권장하지 않음
class Ex implements Runnable{
	boolean suspended = false; //일시정지
    boolean stopped = false; //정지
    
    public void run(){
    	while(!stopped){
        	if(!suspended){
            	/* 쓰레드가 수행할 코드 */
            }
        }
    }
    public void suspend(){suspended = true;}
    public void resume(){suspended = false;}
    public void stop(){stopped = true;}
}
package chapter13;

class RunImplEx1 implements Runnable{

	@Override
	public void run() {
		while(true) {
			System.out.println(Thread.currentThread().getName());
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
			}
		}
		
	}
	
}

public class 쓰레드7_1 {

	public static void main(String[] args) {
		RunImplEx1 r = new RunImplEx1();
		Thread th1 = new Thread(r,"*");
		Thread th2 = new Thread(r,"**");
		Thread th3 = new Thread(r,"***");
		
		th1.start();
		th2.start();
		th3.start();

		try {
			Thread.sleep(2000);
			th1.suspend(); //쓰레드 th1을 잠시 중단
			Thread.sleep(2000);
			th2.suspend();
			Thread.sleep(3000);
			th1.resume(); //쓰레드 th1을 재개
			Thread.sleep(3000);
			th1.stop(); //쓰레드 th1을 강제종료
			th2.stop();
			Thread.sleep(2000);
			th3.stop();
		} catch (InterruptedException e) {
		}
	}

}
package chapter13;

class MyThread7_1 implements Runnable{
	volatile boolean suspended = false; //volatile 변수값이 쉽게 바뀜. 복사본 사용X
	volatile boolean stopped = false;
	
	Thread th;
	
	MyThread7_1(String name){
		th = new Thread(this, name); //Thread(Runnable r, String name)
	}
	
	void start() {
		th.start();
	}
	
	void stop() {
		stopped = true;
	}
	
	void suspend() {
		suspended = true;
	}
	
	void resume() {
		suspended = false;
	}
	
	@Override
	public void run() {
		while(!stopped) {
			if(!suspended) {
				System.out.println(Thread.currentThread().getName());
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e) {
				}
			}
			
		}
			
	}
}	

public class 쓰레드7_1 {

	public static void main(String[] args) {
		MyThread7_1 th1 = new MyThread7_1("*");
		MyThread7_1 th2 = new MyThread7_1("**");
		MyThread7_1 th3 = new MyThread7_1("***");
		
		th1.start();
		th2.start();
		th3.start();

		try {
			Thread.sleep(2000);
			th1.suspend(); //쓰레드 th1을 잠시 중단
			Thread.sleep(2000);
			th2.suspend();
			Thread.sleep(3000);
			th1.resume(); //쓰레드 th1을 재개
			Thread.sleep(3000);
			th1.stop(); //쓰레드 th1을 강제종료
			th2.stop();
			Thread.sleep(2000);
			th3.stop();
		} catch (InterruptedException e) {
		}
	}

}

 

join()

  • 지정된 시간동안 특정 쓰레드가 작업하는 것을 기다림
void join() //작업이 모두 끝날때까지 기다림
void join(long millis) //천분의 일초 동안
void join(long millis, int nanos) //천분의 일초 + 나노초 동안
  • 예외처리를 해야함(InterruptedException이 발생하면 작업 재개)
package chapter13;

class Thread8_1a extends Thread{
	public void run() {
		for(int i = 0; i < 300; i++) {
			System.out.print(new String("-"));
		}
	}
}
class Thread8_1b extends Thread{
	public void run() {
		for(int i = 0; i < 300; i++) {
			System.out.print(new String("|"));
		}
	}
}

public class 쓰레드8_1 {
	static long startTime = 0;
	
	public static void main(String[] args) {
		Thread8_1a th1 = new Thread8_1a();
		Thread8_1b th2 = new Thread8_1b();
		
		th1.start();
		th2.start();
		startTime = System.currentTimeMillis(); //시작시간
		
		try {
			th1.join(); //main쓰레드가 th1의 작업이 끝날때까지 기다림
			th2.join(); //main쓰레드가 th2의 작업이 끝날때까지 기다림
		} catch (InterruptedException e) {
		}

		System.out.println("소요시간 : " + (System.currentTimeMillis()-startTime));
	}

}

 

yield()

  • 남은 시간을 다음 쓰레드에게 양보고하고, 자신(현재 쓰레드)은 실행대기함
  • yield()와 interrupt()를 적절히 사용하면, 응답성과 효율을 높일 수 있음

 

쓰레드의 동기화(synchronization)

  • 멀티 쓰레드 프로세스에서는 다른 쓰레드의 작업에 영향을 미칠 수 있음
  • 진행중인 작업이 다른 쓰레드에게 간섭받지 않게 하려면 '동기화'가 필요
    ※쓰레드의 동기화 : 한 쓰레드가 진행중인 다른 작업을 다른 쓰레드가 간섭하지 못하게 막는 것
  • 동기화하려면 간섭받지 않아야 하는 문장들을 '임계 영역'으로 설정
  • 임계영역은 락(lock)을 얻은 단 하나의 쓰레드만 출입가능(객체 1개에 락 1개)

synchronized를 이용한 동기화

  • synchronized로 임계영역(lock이 걸리는 영역)을 설정하는 방법
    1. 메소드 전체를 임계 영역으로 지정(개수 최소화 영역 최소화)
    2. 특정한 영역을 임계 영역으로 지정
//1. 메소드 전체를 임계영역으로 지정
public synchronized void sum(){
	//....
}

//2. 특정 영역을 임계영역으로 지정
synchronized(객체의 참조변수){
	//....
}
package chapter13;

class Account{
	private int balance = 1000; //private으로 해야 동기화가 의미가 있음
	
	public synchronized int getBalance() {
		return balance;
	}
	
//	public void withdraw(int money) {
	public synchronized void withdraw(int money) { //synchronized로 메소드를 동기화
		if(balance>=money) {
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
			}
			balance-=money;
		}
	}
}

class Runnable9_1 implements Runnable{
	Account account = new Account();
	public void run() {
		while(account.getBalance()>0) {
			//100,200,300 중 한 값을 임의로 선택해서 출금
			int money = (int)(Math.random()*3+1)*100;
			account.withdraw(money);
			System.out.println("balance : " + account.getBalance());
		}
	}
}

public class 쓰레드9_1 {
	
	public static void main(String[] args) {

		Runnable r = new Runnable9_1();
		new Thread(r).start(); //ThreadGroup에 의해 참조되므로 gc대상이 아님
		new Thread(r).start(); //ThreadGroup에 의해 참조되므로 gc대상이 아님
		
		
	}

}

 

wait()와 notify()

  • 동기화의 효율을 높이기 위해 wait(), notify()를 사용
    wait() 기다리기, notify() 통보, 알려주기
  • Object클래스에 정의되어 있으며, 동기화 블록 내에서만 사용할 수 있음
    wait() : 객체의 lock을 풀고 쓰레드를 해당 객체의 waiting pool에 넣음
    notify() : waiting pool에서 대기중인 쓰레드 중의 하나를 깨움(귓속말)
    notifyAll() : waiting pool에서 대기중인 모든 쓰레드를 깨움(방송)

 

728x90

'organize > 자바' 카테고리의 다른 글

Java36  (0) 2024.08.23
Java 35  (0) 2024.08.22
Java 33  (0) 2024.08.21
Java 32  (0) 2024.08.20
Java 31  (0) 2024.08.15