KDT/Java

240321 Java - 스레드 3

001cloudid 2024. 3. 21. 17:41
728x90

스레드

웹 서버 내에서 처리하기 위해서 스레드를 발생시켜 응답을 처리

 

인터럽트

  • 하나의 프로그램 실행을 하드웨어적인 방법으로 중단하고 후에 재개할 수 있도록 다른 프로그램의 실행으로 옮기는 것
  • 어떤 프로그램의 실행 중에 외부로부터의 몇 가지 사건에 의해 그 프로그램의 실행이 일시 정지되어, 그 사건에 대응한 다른 프로그램이 먼저 실행되는 것을 '인터럽트'라고 함
  • 인터럽트 되어 실행된 프로그램이 완료되면 원래 프로그램의 실행이 중단점으로부터 재개
  • 인터럽트는 하나의 명령의 실행마다 일어날 가능성이 있음
  • 인터럽트를 일으키는 인터럽트 사건 또는 인터럽트를 발생시키는 주된 원인으로는 컴퓨터의 내부 구성 부품의 고장, 정의되어 있지 않는 명령의 발생, 자리 수가 넘침, 기억 보호 위반, 전원 및 지진에 의한 이상, 장치의 오동작, 입출력 장치의 동작 완료, SVC(Super Visor Call) 명령 등이 있음

 

쓰레드 라이프 사이클

New(start() 메소드 호출) <-> Runnable(실행대기) <-반복-> 실행(Running 상태) <-> Blocked(일시정지) ->

Dead(Run() 메소드 완료시)

 

동기화

  • 다수의 스레드가 공유 데이터에 동시에 접근하는 경우 공유 데이터의 값에 예상치 못한 결과가 발생할 가능성이 있음
  • 스레드 사이의 실행순서, 제어, 공유 데이터에 대한 접근을 원활하게 하는 기법
  • 멀티 스레드 프로세스에서는 다른 스레드의 작업에 영향을 미칠 수 있음
  • 여러 스레드가 같은 자원을 공유하기 때문에 메모리도 공유해서 사용
  • 어떤 한 스레드가 작업을 마치지 못하고 다음 스레드로 사용권이 넘어 갔을 때 현재 진행중이던 작업에 대하여 다른 스레드가 간섭하지 못하게 막는 것
  • 다른 스레드들에게 간섭받지 않아야 하는 문장들을 그룹(임계영역)으로 묶어서 관리해야 함
package test18;

//동기화(Synchronization)
//하나의 객체 내의 자원을 공유해서 사용하는 경우 지정
//임계영역 안의 현재 작업중인 스레드가 수행을 끝내기 전까지는 다른 스레드가 작업하지 못함


class Ticketing{
	
	int ticketNum = 1; //남은 티켓 수
	
	public void ticketing() {
		if(ticketNum > 0) {
			System.out.println(Thread.currentThread().getName() + "가 티켓팅 성공"); //Thread.currentThread().getName() 스레드 이름
			ticketNum -= 1;
		} else {
			System.out.println(Thread.currentThread().getName() + "가 티켓팅 실패");
		}
		System.out.println(Thread.currentThread().getName()+"가 티켓팅 시도 후 남은 티켓수 : " + ticketNum);
	}
	
}

class TicketingThread implements Runnable{

	Ticketing ticket = new Ticketing();

	@Override
	public void run() {
		ticket.ticketing();
		
	}
	
}

public class Synchronization1 {

	public static void main(String[] args) {
		
		TicketingThread tt = new TicketingThread();
		Thread t1 = new Thread(tt,"스레드1");
		Thread t2 = new Thread(tt,"스레드2");
		Thread t3 = new Thread(tt,"스레드3");
		
		t1.start();
		t2.start();
		t3.start();
		

	}

}

 

동기화

package test18;

//동기화(Synchronization)
//하나의 객체 내의 자원을 공유해서 사용하는 경우 지정
//임계영역 안의 현재 작업중인 스레드가 수행을 끝내기 전까지는 다른 스레드가 작업하지 못함


class Ticketing{
	
	int ticketNum = 1; //남은 티켓 수
	
	//스레드 동기화(synchronized) 키워드를 붙여 놓은 메소드는 첫 번째 스레드가 수행을 끝내기 전까지 두 번째 스래드가 접근하지 못함
	//두 번째 스랟드가 수행을 끝내기 전까지 세 번째 스레드가 접근하지 못함,....
	public synchronized void ticketing() {
		if(ticketNum > 0) {
			System.out.println(Thread.currentThread().getName() + "가 티켓팅 성공"); //Thread.currentThread().getName() 스레드 이름
			ticketNum -= 1;
		} else {
			System.out.println(Thread.currentThread().getName() + "가 티켓팅 실패");
		}
		System.out.println(Thread.currentThread().getName()+"가 티켓팅 시도 후 남은 티켓수 : " + ticketNum);
	}
	
}

class TicketingThread implements Runnable{

	Ticketing ticket = new Ticketing();

	@Override
	public void run() {
		ticket.ticketing();
		
	}
	
}

public class Synchronization1 {

	public static void main(String[] args) {
		
		TicketingThread tt = new TicketingThread();
		Thread t1 = new Thread(tt,"스레드1");
		Thread t2 = new Thread(tt,"스레드2");
		Thread t3 = new Thread(tt,"스레드3");
		
		t1.start();
		t2.start();
		t3.start();
		

	}

}

 

package test18;

import java.time.LocalDate;

class Member extends Thread{
	
	String place; //목적지
	LocalDate ld; //날짜 객체 생성
	int count = 0;
	
	//일반 생성자
	public Member(String place, LocalDate ld) {
		this.place = place;
		this.ld = ld;
	}

	@Override
	public synchronized void run() {
		
		for(int i = 1; i<=1;i++) {
			System.out.println("목적지는 " + place + "출발일은 " + ld);
			System.out.println("스레드 이름 : " + Thread.currentThread().getName() + i);
			count++;
			System.out.println("count : " + count);
			System.out.println();
			
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		
	}
	
}

public class Synchronization2 {

	public static void main(String[] args) {

//		LocalDate ld = LocalDate.now();
//		System.out.println(ld);
		
		//일반 생성자 : 목적지 예매일자
		Member m1 = new Member("집", LocalDate.now());
		
		Thread thread1 = new Thread(m1,"스레드1");
		Thread thread2 = new Thread(m1,"스레드2");
		Thread thread3 = new Thread(m1,"스레드3");
		Thread thread4 = new Thread(m1,"스레드4");

		thread1.start();
		thread2.start();
		thread3.start();
		thread4.start();
		
		
	}

}

 

구분

 

package test18;

import java.time.LocalDate;

class Member extends Thread{
	
	String place; //목적지
	LocalDate ld; //날짜 객체 생성
	int count = 0;
	
	//일반 생성자
	public Member(String place, LocalDate ld) {
		this.place = place;
		this.ld = ld;
	}

	@Override
	public void run() {
		synchronized(this) {
		for(int i = 1; i<=1;i++) {
			System.out.println("목적지는 " + place + "출발일은 " + ld);
			System.out.println("스레드 이름 : " + Thread.currentThread().getName() + i);
			count++;
			System.out.println("count : " + count);
			System.out.println();
			
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		}
	}
	
}

public class Synchronization2 {

	public static void main(String[] args) {

//		LocalDate ld = LocalDate.now();
//		System.out.println(ld);
		
		//일반 생성자 : 목적지 예매일자
		Member m1 = new Member("집", LocalDate.now());
		
		Thread thread1 = new Thread(m1,"스레드1");
		Thread thread2 = new Thread(m1,"스레드2");
		Thread thread3 = new Thread(m1,"스레드3");
		Thread thread4 = new Thread(m1,"스레드4");

		thread1.start();
		thread2.start();
		thread3.start();
		thread4.start();
		
		
	}

}

 

package test18;

//wait() : 동기화된 스레드를 대기
//notify() : 동기화된 스레드(wait)를 깨움


//입출금을 처리하는 클래스
class Account{
	
	int money = 0; //멤버 변수
	
	public int showMoney() {
		return money;
	}
	
	//입금하는 메소드
	public synchronized void setMoney() {//동기화
		
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		this.money +=200000;
		System.out.println("화성 갈끄니까 " + this.showMoney());
		this.notify(); //wait() 메소드를 깨울때 사용 -> 입금 메소드 수행이 끝나면
	}
	
	//출금하는 메소드
	public synchronized void getMoney() {
		while(money <= 0) {
			
			try {
				this.wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
			this.money -= 300000;
			System.out.println("한강가기 전 금액 " + this.showMoney());
		}
	}

class MyMoney extends Thread{
	
	Account account; //입출금을 담당하는 Account 클래스의 객체를 생성해서 멤버 변수
	
	MyMoney(Account account){
		this.account = account;
	}

	@Override
	public void run() {
		for(int i =0; i<10; i++) {
			account.getMoney();
		}
	}
}

class MyAccount extends Thread{
	
	Account account;
	
	MyAccount(Account account){
		this.account = account;
	}

	@Override
	public void run() {
		for(int i =0; i<10; i++) {
			account.setMoney();
		}
	}
	
}

public class Synchronization3 {

	public static void main(String[] args) {
		
		Account account = new Account();
		System.out.println(account);
		System.out.println("================");
		
		MyMoney mm = new MyMoney(account);
		MyAccount mc = new MyAccount(account);
		
		mm.start();
		mc.start();

	}

}

 

728x90

'KDT > Java' 카테고리의 다른 글

240327 Java - 제네릭 2  (0) 2024.03.27
240325 Java - 제네릭 1  (0) 2024.03.25
240320 Java - 스레드 2  (0) 2024.03.20
240318 Java - 스트림 3, 스레드 1  (0) 2024.03.18
240314 Java - 람다식 2, 스트림 1  (0) 2024.03.14