15일차 : 스레드의 동기화

---------------------------------------      package test01.thread;      ----------------------------------------------------------

 

 

임시 저장소에 데이터를 저장하는 스레드

package test01.thread; // 임시 저장소에 데이터를 저장하는 스레드 class TempThread extends Thread{ //Message msg=new Message();==>두 개의 자원을 사용하겠다고 여기에 이렇게주면 안된다. private Message msg; //main 메소드에서 생성된 객체를 참조해 온다. public TempThread(Message msg){ this.msg=msg; } public void run(){ char[] data={'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J'}; //다운로드 할 데이터. 이것을 msg.set~로 옮겨야 함. for(int i=0; i<data.length; i++){ //다운로드 할 데이터를 임시 저장소에 저장하기 msg.setMsg(String.valueOf(data[i])); //setMsg는 파라미터 값을 돌면서 계속 연결해주는 역할 //for(int j=0; j<=1000; j++); //시간 지연하기 } System.out.println("임시저장공간에 다운로드 완료"); } } // 임시 저장소의 데이터를 파일로 저장하는 스레드 class WriteThread extends Thread{ private Message msg; //main 메소드에서 생성된 객체를 참조해 온다. public WriteThread(Message msg){ this.msg=msg; } public void run(){ System.out.println("파일로 저장 시작!"); System.out.println(msg.getMsg()); System.out.println("파일에 저장 완료!"); } } public class MainTest { public static void main(String[] args) { Message msg=new Message();//스레드간에 공유자원이 될 객체 TempThread thread1=new TempThread(msg); WriteThread thread2=new WriteThread(msg);//msg 객체를 파일로 저장 thread1.start(); thread2.start(); } }

 

 

 

입금 기능을 갖는 스레드

package test01.thread;
//동기화
class InputThread extends Thread{//입금 기능을 갖는 스레드
	private Bank bank;
	public InputThread(Bank bank){
		this.bank=bank;
	}
	public void run(){
		synchronized (bank) {	//싱크로나이즈드. (bank) =공유자원	동기화 처리하기(lock 이 걸림)
		System.out.println("입금 처리중");
		bank.input(1000);	//공유자원
		for(int i=1; i<=100000000; i++);//;을 안찍어주면 계속 루프를 돌기 때문에 찍어준다. 시간지연(입금 처리중이라고 가정하자.)
		System.out.println("입금 완료!");
		System.out.println("입금 후 잔액: " + bank.getMoney());
		}
	}
}
class OutputThread extends Thread{
	private Bank bank;
	public OutputThread(Bank bank){
		this.bank=bank;
	}
	public void run(){
		synchronized (bank){//동기화 처리하기(lock 이 걸림)
		System.out.println("출금 처리중");
		bank.output(2000);
		for(int i=1; i<=100000000; i++);//시간지연(입금 처리중이라고 가정하자.)
		System.out.println("출금 완료!");
		System.out.println("출금 후 잔액: "+bank.getMoney());
		}
	}
}
public class MainTest01 {
	public static void main(String[] args) {
			Bank bank=new Bank(5000);
			new OutputThread(bank).start();
			new OutputThread(bank).start();
			new OutputThread(bank).start();
			new InputThread(bank).start();
			new OutputThread(bank).start();
			new OutputThread(bank).start();
	}
}


 

 

 

 

 

공유 자원이 될 객체

package test01.thread; //공유 자원의 될 객체 public class Bank { private double money;//잔액 public Bank(double money){ this.money=money; } public void input(double m){//입금기능 money+=m; } public void output(double m){//출금기능 if(money<m){ //입금 된 돈이 적으면 System.out.println("잔액부족"); return;//메소드 끝내기 } money-=m; } public double getMoney(){ return money; } }

 

스레드간의 객체 공유하기

package test01.thread;
// 스레드 간의 객체 공유하기
//공유 될 클래스
public class Message {
	private String msg="";
	public void setMsg(String msg){
		this.msg+=msg;
	}
	public String getMsg(){return msg;}
}


---------------------------------------      package test02.thread;      ----------------------------------------------------------

 

Test02 InputThread

package test02.thread;

class InputThread extends Thread{
	private Bank bank;
	public InputThread(Bank bank){
		this.bank=bank;
	}
	public void run(){
		//bank 객체 자체에서 동기화 처리가 되어있으므로 사용하는 곳에서는 동기화 처리를 하지 않는다.
		bank.input(1000);
	}
}
class OutputThread extends Thread{
	private Bank bank;
	public OutputThread(Bank bank){
		this.bank=bank;
	}
	public void run(){
		bank.output(2000);
	}
}
public class MainTest {
	public static void main(String[] args) {
		Bank bank=new Bank(5000);
		new OutputThread(bank).start();
		new OutputThread(bank).start();
		new InputThread(bank).start();
		new OutputThread(bank).start();
	}
}

 

 

 

 

Test02 공유자원이 될 객체

package test02.thread; //공유 자원의 될 객체 public class Bank { private double money;//잔액 public Bank(double money){ this.money=money; } public synchronized void input(double m){ //동기화 메소드 System.out.println("입금 처리중"); for(int i=1; i<=100000000; i++); money+=m; System.out.println("입금 처리 완료"); System.out.println("입금 후 잔액: " +money); } public synchronized void output(double m){ //동기화 메소드 System.out.println("출금 처리중"); for(int i=1; i<=100000000; i++); if(money<m){ //입금 된 돈이 적으면 System.out.println("잔액부족"); return;//메소드 끝내기 } money-=m; System.out.println("입금 처리 완료"); System.out.println("입금 후 잔액: " +money); } public double getMoney(){ return money; } }

---------------------------------------      package test03.thread;      ----------------------------------------------------------

 

Test03 임시 저장 공간에 다운로드 및 파일저장

package test03.thread; class TempThread extends Thread{//템프스레드는 Message msg 객체를 가지고 있지 private Message msg; public TempThread(Message msg){ this.msg=msg; } public void run(){ synchronized (msg) { //동기화 System.out.println("임시 저장 공간에 다운로드 시작"); char[] data={'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J'};//다운로드 할 데이터. 이것을 msg.set~로 옮겨야 함. for(int i=0; i<data.length; i++){ //다운로드 할 데이터를 임시 저장소에 저장하기 msg.setMsg(String.valueOf(data[i]));//setMsg는 파라미터 값을 돌면서 계속 연결해주는 역할 for(int j=0; j<=1000; j++);//시간 지연하기 } System.out.println("임시저장공간에 다운로드 완료"); msg.notify();//wait 하고 있는 객체를 깨운다. msg.setStatus(true); //참이면 32행이 false 로 실행하지 않고 파일 저장 시작~ 뜸 } } } // 임시 저장소의 데이터를 파일로 저장하는 스레드 class WriteThread extends Thread{ private Message msg; //main 메소드에서 생성된 객체를 참조해 온다. public WriteThread(Message msg){ this.msg=msg; } public void run(){ synchronized(msg) { if(msg.isStatus()==false){//생산자 스레드가 아직 notify 하지 않는 경우 ==> wait 가 수행되어야 함 try{ msg.wait();//다른 스레드에서 notify 메소드로 깨울 때까지 wait 상태가 됨. synchronized 블록 안에서만 사용 가능! }catch(InterruptedException ie){ System.out.println(ie.getMessage()); } } System.out.println("파일로 저장 시작!"); System.out.println(msg.getMsg()); System.out.println("파일에 저장 완료!"); } } } public class MainTest { public static void main(String[] args) { Message msg=new Message(); //스레드간에 공유자원이 될 객체 TempThread thread1=new TempThread(msg); WriteThread thread2=new WriteThread(msg);//msg 객체를 파일로 저장 thread1.start(); thread2.start(); } }

 

 

 

 

 

Test03 스레드 간의 객체 공유하기

package test03.thread;
// 스레드 간의 객체 공유하기
// 공유될 클래스
public class Message {
	private String msg="";
	private boolean status=false;
	public void setStatus(boolean status){
		this.status = status;
	}
	public boolean isStatus(){
		return status;
	}
	public void setMsg(String msg){	//setMsg : setter 메소드 라고 부름
		this.msg+=msg;
	}
	public String getMsg(){	//getMsg : getter 메소드라고 부름
		return msg;
	}
}


---------------------------------------      package test04.thread;      ----------------------------------------------------------

 

Test04 ThreadJoin

package test04.thread;

import java.util.Random;

class MyThread1 extends Thread{
	public void run(){
		Random rnd=new Random();
		for(int i=1;i<=100;i++){
			int n=rnd.nextInt(100);
			System.out.print("발생된난수:"+n);
			if(i%10==0) System.out.println();
		}
		System.out.println("자식스레드 종료");
	}
}
public class ThreadJoin {
	public static void main(String[] args) {
		MyThread1 thread=new MyThread1();
		thread.start();
		try{
			thread.join();	//부모 스레드가 자식 스레드가 종료 될 때까지 기다림
		}catch(InterruptedException ie){
			System.out.println(ie.getMessage());
		}
		System.out.println("메인스레드종료");
	}
}

 

 

 

 

Test04 hreadStop

package test04.thread;

import java.util.Random;

class MyThread extends Thread{
	private boolean status=false;
	public void run(){
		Random rnd=new Random();
		status=true;
		while(status){
			int n=rnd.nextInt(100);
			System.out.println("발생된난수:"+n);
		}
	}
	public void stopMyThread(){
		status=false;
	}
}
public class ThreadStop {
	public static void main(String[] args) {
		MyThread th=new MyThread();
		th.start();//스레드 실행하기
		try{
			Thread.sleep(3000);
		}catch(InterruptedException ie){}
		th.stopMyThread();//스레드 종료하기
	}
}
// 메인 스레드에서 th.stopMyThread(); 호출