본문 바로가기

언어/Java

Thread pop, push

class Push {
	Share s;
	public Push(Share s) {
		this.s=s;
	}
}

class Pop {
	Share s;
	public Pop(Share s) {
		this.s=s;
	}
}

class Share{
	int i;
}

public class ThreadShareTest {
	public static void main(String[] args) {
		Share s = new Share();
		Push push = new Push(s);
		Pop pop = new Pop(s);
		System.out.println(pop.s.i);
	}
}

결과

class Share{
	private int i;	// 인스턴스변수
	public void push() {	// i값 1 증가
		for(int i = 0; i<100; i++) {
			System.out.print("Before push:i=" + this.i);
			this.i++;
			System.out.println(", After push:i=" + this.i);
		}
	}
	public void pop() {	// i값 1 증가
		for(int i = 0; i<100; i++) {
			System.out.print("Before pop:i=" + this.i);
			this.i--;
			System.out.println(", After pop:i=" + this.i);
		}
	}
}

class Push extends Thread {
	private Share s;
	Push(Share s) {
		this.s=s;
	}
	@Override
	public void run() {
		this.s.push();
	}	
}

class Pop extends Thread {
	private Share s;
	Pop(Share s) {
		this.s=s;
	}
	@Override
	public void run() {
		this.s.pop();
	}
}

public class ThreadShareTest {
	public static void main(String[] args) {	// 한 java파일에 여러개 class이면 main을 가지고 있는 애만 public
		Share s;
		s = new Share();
		
//		Push push = new Push();
//		push.s=s; 이렇게 해도되는데 그건 push class가 Share s; 일때
		// push class, share class에 private Share s 이면 아래처럼 해야함
		Push push = new Push(s);
		Pop pop = new Pop(s);
		
		push.start();
		pop.start();
	}
}

처리결과는 떨어지나 before after 유지

※ i의 계산식 완료하지 못하고 스레드 종료되서 옳지않은 값들 가짐. i를 공유중이다.
값이 온전히 가지려면 계산하는 동안에는 점유율 뺏기면 안된다
스레드들 사이에서 공유되었을 때 위험한 자료는 임계영역(critical section)을 설정해서
위험한 데이터의 접근을 못하도록 동기화처리를 해야한다. 공유객체 사용하는 다른 Thread에게 CPU를 뺏기지 말아야한다.
공유객체 사용안하는 다른 Thread에게는 CPU를 뺏겨도 상관없음
동기화는 lock을 거는 것. 잠금장치있는 동안에는 cpu 뺏기지마라
동기화 = synchronized()

wait

※ wait 
동기화된 스레드의 일시중지용 메소드, 자동으로 깨어나지 않는다.
현재 객체를 공유하고 있는 current thread를 중지

공유객체를 사용하지 않으면(동기화 안되어있으면) 소용없다.
하나는 wait(), 하나는 notify()

 https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/Object.html#wait() 

* yield()
run 상태에 있는 메서드를 Runnable 상태로 이동시키는게 yield 메소드
다른 스레드에 양보한다.

* join
스레드가 죽을 때까지 기다림

public static void main() {
	OneThread one = new ~();
	one.start()
	one.join();
} // one 스레드가 끝날때까지 main이 기다림
// 기다렸다가 one 스레드가 만들어낸 결과값을 사용하고 싶을 때
class Share{
	private int i;	// 인스턴스변수
	public void push() {	// i값 1 증가
		for(int i = 0; i<100; i++) {
			synchronized(this) {	//synchronized(공유객체), 짧게 쓰는걸 권장			//잠금장치
				this.notify(); // 여기서 notify는 java.lang.object의 최상위 메소드
				//이 공유객체를 사용하는 wait된 스레드를 깨운다
				// waiting된 메서드를 깨운다
                // wait 여러개 있어도 큐 자료구조 형태라서 가장 먼저 wait된 스레드만 깨움
				// 모두를 깨우고싶으면 notifyAll();
				System.out.print("Before push:i=" + this.i);
				this.i++;
				System.out.println(", After push:i=" + this.i);
			}
		}
	}
			
		/*	
		synchronized(this) {	// 이렇게 써버리면 중간에 pop()이 치고 들어오지 않아서
        						// 스레드의 효과 없다
			for(int i = 0; i<100; i++) {
				System.out.print("Before push:i=" + this.i);
				this.i++;
				System.out.println(", After push:i=" + this.i);
			}
		}
		*/				
	public void pop() {	// i값 1 증가
		for(int i = 0; i<100; i++) {
			synchronized(this) { //잠금장치
				if(this.i==0) {
					try {
						this.wait();// 여기서 wait는 java.lang.object의 최상위 메소드 wait
                        			//그래서 그냥 wait 해도됨 
									// 이 공유객체를 사용하는 현재스레드를 일시중지한다.
					} catch (InterruptedException e) {
						e.printStackTrace();
					}	
				}
				System.out.print("Before pop:i=" + this.i);
				this.i--;
				System.out.println(", After pop:i=" + this.i);
			}
		}
	}
}

class Push extends Thread {
	private Share s;
	Push(Share s) {
		this.s=s;
	}
	@Override
	public void run() {
		this.s.push();
	}
}

class Pop extends Thread {
	private Share s;
	Pop(Share s) {
		this.s=s;
	}
	@Override
	public void run() {
		this.s.pop();
	}
}

public class ThreadShareTest {
	public static void main(String[] args) {	// 한 java파일에 여러개 class이면
    											// main을 가지고 있는 애만 public
		Share s;
		s = new Share();
		
//		Push push = new Push();
//		push.s=s; 이렇게 해도되는데 그건 push class가 Share s; 일때
		// push class, share class에 private Share s 이면 아래처럼 해야함
		Push push = new Push(s);
		Pop pop = new Pop(s);
		
		push.start();
		pop.start();

	}

}

wait 쓸때 결과

'언어 > Java' 카테고리의 다른 글

스레드 상태  (0) 2023.08.16
스레드 이름 부여하기  (0) 2023.08.16
ThreadSleep  (0) 2023.08.16
멀티 스레드  (0) 2023.08.16
성능 향상 스트림  (0) 2023.08.15