본문 바로가기

전공

Java_예외 처리, 스레드

예외처리

  • 예외가 발생하는 경우
     - 정수를 0으로 나누는 경우 / 배열의 첨자가 범위를 벗어났을 경우 / 부적절한 형 변환이 발생한 경우 / 입출력 시 인터럽트가 발생한 경우 / 지정한 파일일 존재하지 않는 경우 등
  • 에러 발생 시 에러 메시지를 출력하기 위해 제공 되는 메서드
     - getMessage() : 해당 객체에 포함된 에러 메시지
     - toString() : 예외 클래스와 해당 객체에 포함된 에러 메시지
     - printStackTrace() : 예외가 발생하기까지의 메소드 호출 순서를 화면에 출력
  • 다중 try - catch - finally
    try{
      예외를 발생시킬 가능성이 있는 문장들;
    }catch(예외 타입1){
      예외 타입1 발생 시 처리할 문장들;
    }catch(예외 타입2){
      예외 타입2 발생 시 처리할 문장들;
    }finally{
      항상 실행할 문장들;
    }
  • throws
     - 예외가 발생한 메소드를 호출한 곳으로 예외 처리를 넘겨준다.
     - throws 사용시 반드시 try - catch 문으로 예외 사항 처리해야함
     - 접근 제한자 메소드 이름() throws 예외 클래스 이름들 { // 메소드가 수행 할 작업들; }
  • 반드시 예외 사항 처리 필요한 곳
     - 파일 입출력, 메모리 입출력, 데이터 베이스 입출력, 네트워크 입출력

예외 처리 클래스

  • IOException 클래스
     - 데이터를 입출력할 때 발생할 수 있는 에러 이벤트를 처리하는 클래스
  • NullPointerException 클래스
     - 참조할 메모리가 없을 경우 발생하는 이벤트를 처리하는 클래스
  • ArrayIndexOutOfBoundsException 클래스
     - 배열의 범위를 벗어났을 때 발생하는 이벤트를 처리하는 클래스
  • FileNotFoundException 클래스
     - 처리할 파일이 없을 경우 발생하는 이벤트를 처리하는 클래스
  • Exception 클래스
     - 모든 예외 처리 클래스의 상위 클래스

스레드

  • 스레드 : 어떠한 프로그램 내에서, 특히 프로세스 내에서 실행되는 흐름의 단위
  • 자바 스레드 지원되므로 멀티스레드를 쉽게 구현가능하고, 안정성과 효율성을 보장할 수 있다.
  • main()도 하나의 스레드이다.

Thread 클래스를 상속하는 방법

작성 순서 사용 예
1. 스레드 클래스 생성
 - Thread 클래스 상속
 - 스레드 기능 구현 : run()구현
public class FThread extends Thread{
     public void run(){
          // 처리 내용
     }
}
2. 스레드 객체 생성
 - new 연산자
FThread th = new FThread();
3. 스레드 실행
 - start() 메소드 호출
th.start();
class DerivedThread extends Thread{
	public void run(){
    	for(int i=0; i<50; i++)
        	System.out.print(i + "\t");
    }
}
public class ThreadEx{
	public static void main(String[] args){
    	System.out.println("프로그램 시작");
        DerivedThread d1 = new DerivedThread();
        DerivedThread d2 = new DerivedThread();
        d1.start();
        d2.start();
        System.out.println("프로그램 종료");
        // d1, d2, 프로그램 종류 메시지가 전부 번갈아 가며 실행된다.
        // 실행될 때마다 다른 결과 나옴
        // Thread Scheduler가 실행 시간과 순서를 관리하기 때문 
    }
}

 

Runnable 인터페이스를 구현하는 방법

 - Thread 클래스를 상속하는 방법과 큰 차이는 없지만 Thread 클래스를 상속받는 것이 더 편리하다.
 - 만약 다른 클래스를 상속하는 경우 다중상속을 지원하지 않기 때문에 인터페이스를 구현하여 스레드 프로그램 작성

작성 순서 사용 예
1. 스레드 클래스 생성
 - Runnable 인터페이스를 구현
 - 스레드 기능 구현 : run() 구현
public class SThread implements Runnable{
     public void run(){
          // 처리 내용
     }
}
2. 스레드 객체 생성
 - new 연산자
SThread st = new SThread();
Thread th = new Thread(st);
// Thread th = new Thread(new STread());
3. 스레드 실행
 - start() 메소드 호출
th.start();
class Top implements Runnable{
	public void run(){
    	for(int i=0; i<50; i++)
        	System.out.println(i);
    }
}
public class Runnable2Ex{
	public static void main(String[] args){
    	System.out.println("프로그램 시작");
        // Runnable 구현 객체 만들기
        Top t = new Top();	
        Thread th1 = new Thread(t);
        Thread th2 = new Thread(t);
        th1.start();
        th2.start();
        System.out.println("프로그램 종료");
    }
}

 

스레드의 상태

  • start 상태
     - 시작 상태 ( start() 메서드 호출했을 때 )
     - Runnable 상태로 변한다.
  • Runnable 상태
     - 동작할 수 있는 상태
     - 여러개 스레드 존재 가능
  • Run 상태
     - 동작 상태 ( Runnable 상태에서만 Run 상태가 될 수 있다. )
     - 하나의 스레드만 동작 가능
  • NotRunnable 상태
     - 대기 상태
     - Run 상태로 진입할 수는 없지만 Dead 상태는 아니다.
  • Dead 상태
     - 종료 상태
     - run() 메소드의 종료 = 스레드 종료
  • 스레드 제어 메소드
     - sleep(시간) 메소드 : 일정 시간 동안 NotRunnable 상태가 되었다 Runnable 상태가 된다. ( 시간 단위 : 1/1000초 )
     - wait() 메소드 : NotRunnable 상태가 됨.
     - notify() 메소드 : Runnable 상태가 됨

스레드 우선순위

  • 우선순위(priority)
     - 어떤 스레드를 더 먼저 실행할 수 있는 권한
     - 여러 매소드 중 우선순위가 높은 스레드 실행
  • 우선권 상수
     - public static final int MAX_PRIORITY     // 가장 높다, 10
     - public static final int MIN_PRIORITY     // 가장 낮다, 1
     - public static final int NORM_PRIORITY     // 중간, 5
  • 메소드
     - public final int getPriority() : 우선 순위를 얻어오는 메소드
     - public final void setPriority(int newPriority) : 우선 순위를 지정하는 메소드
     - public final void setName(String name) : 스레드 이름 지정하는 메소드
     - public final String getName() : 스레드 이름 얻어오는 메소드
class Top implements Runnable{
	public void run(){
    	for(int i=0; i<30; i++)
        	System.out.print((Thread.currentThread()).getName() + i + "\t");
            // 현재 실행되는 스레드의 이름 + i + "\t"
    }
}
public class Runnable3Ex{
	public static void main(String[] args){
    	System.out.println("프로그램 시작");
        
        Top p = new Top();
        Thread th1 = new Thread(p, "a");	// 스레드 생성 + 이름 지정
        Thread th2 = new Thread(p, "b");
        
        th1.setName("new_a");	// 스레드 이름 변경
        th2.setName("new_b");
        
        th1.setPriority(9);	// 스레드 우선 순위 변경
        th2.setPriority(th2.MIN_PRIORITY);
        
        System.out.println(th1.getPriority());	// 우선 순위 출력
        System.out.println(th1.getPriority());
        
        th1.start();	// 스레드 시작
        th2.start();
        
        System.out.println("프로그램 종료");
    }
}

 

스레드 동기화

  • 동기화(Synchronization)
     - 하나의 스레드가 끝날 때까지 락(lock)을 걸어서 다른 스레드가 동일한 데이털르 갱신하지 못하도록 하는 것.
     - synchronized 키워드를 이용해 동기화
     - 동기화된 메소드는 락을 설정하여 완료될 때까지 유지하며, 동시에 호출할 수 없다.
  • 메소드 전체를 동기화 하는 방법
         접근제한자 synchronized 반환형 메소드이름( 인자 ) { 실행 코드 }
// 두개의 스레드가 독립적으로 합을 구하는 프로그램
class Summing{
	private int sum;
    public synchronized void sumTo(int num){	// 메소드 전체를 동기화
    	sum = 0;
        for(int i=1; i<=num; i++){
        	sum += i;
            System.out.print("스레드 : " + Thread.currentThread().getName());
            System.out.println("의 1 ~ " + i + "까지의 합은 " + sum);
            try{
            	Thread.sleep(500);	// 0.5초
            }catch(InterruptedException e){}
        }
    }//sumTo
    public int getSum(){ return sum; }
}
class MultiThreadEx extends Thread{
	private Summing sum;
    private int num;
    public MultiThreadEx(String s, Summing sum, int num){
    	super(s);
        this.sum = sum;
        this.num = num;
        System.out.println("스레드 : " + this.getName() + "가 시작됨");
    }
    public void run(){
    	sum.sumTo(num);
        System.out.println("스레드 : " + this.getName() + "가 종료됨");
    }
    public static void main(String[] args){
    	Summing sum = new Summing();
        MultiThreadEx a = new MultiThreadEx("A", sum, 5);
        MultiThreadEx b = new MultiThreadEx("B", sum, 5);
        a.setPriority(8);
        b.setPriority(10);
        a.start();
        b.start();
    }
}
  • 특정 블록을 지정하여 객체를 동기화하는 방법
         synchronized( 객체 변수 ){ 실행 코드 }
// 공동으로 사용하는 통장에 각자 카드를 가질 때 자유롭게 입출금 할 수 있는 프로그램
class Bank{
	private int money = 10000;
    public int getMoney(){ return this.money; }
    public void setMoney(int money){ this.money = money; }
    public void saveMoney(int save){
    	int m = this.getMoney();
        try{
        	Thread.sleep(500);
        }catch(InterruptedException e){
        	e.printStackTrace();
        }
        this.setMoney(m + save);
    }
    public void minusMoney(int minus){
    	int m = this.getMoney();
        try{
        	Thread.sleep(500);
        }catch(InterruptedException e){
        	e.printStackTrace();
        }
        this.setMoney(m - minus);
    }
}
class Family1 extends Thread{
	public void run(){
    	synchronized(BankEx.mybank){	// 특정 블록을 지정하여 객체를 동기화
        	BankEx.mybank.saveMoney(5000);
        }
        System.out.println("saveMoney(5000) : " + BankEx.mybank.getMoney());
    }
}
class Family2 extends Thread{
	public void run(){
    	synchronized(BankEx.mybank){	// 특정 블록을 지정하여 객체를 동기화
        	BankEx.mybank.minusMoney(2000);
        }
        System.out.println("minusMoney(2000) : " + BankEx.mybank.getMoney());
    }
}
public class BankEx{
	public static Bank mybank = new Bank();
    public static void main(String[] args){
    	System.out.println("원금 : " + mybank.getMoney());
        Family1 f1 = new Family1();
        Family2 f2 = new Family2();
        f1.start();
        try{
        	Thread.sleep(200);
        }catch(InterruptedException e){
        	e.printStackTrace();
        }
        f2.start();
    }
}

 

'전공' 카테고리의 다른 글

파이썬_모듈, 패키지  (2) 2024.12.19
자료구조_알고리즘  (1) 2024.12.17
Java_컬렉션 제네릭  (7) 2024.10.08
파이썬_변수, 자료형 / 제어문, 반복문 / 함수  (0) 2024.07.10
자료구조_비선형 구조  (0) 2024.07.09