3월 ~ 5월) 자바/java

15Day - (다중쓰레드)WrapperApp/ StringBufferApp / SingleThreadApp & SingleThread / MultiThreadApp & MultiThreadOne & MultiThreadTwo / Account & AccountUser & AccountUserApp / ConsoleCaluelateApp (숙제)

첼로그 2023. 4. 18. 23:38

WrapperApp

package xyz.itwill.lang;
// Wrapper 클래스 : 원시형을 클래스로 선언한 자료형을 일괄적으로 표현하기 위한 이름
// > Byte, Short, Integer, Long, Float, Double, Character, Boolean
// > 원시형 대신객체로 표현하기 위한 사용하는 클래스

/*
int num1 = 100;
int num2 = 200;
int num3 = num1 + num2;

System.out.println("합계 = " + num3);

*/


/*
// Integer 클래스 : 정수값을 저장하기 위한 클래스
// Integer.valueOf(Object i ) : 매개변수로 값을 전달받아 정수값이 저장된 Integer 객체를 반환하는 메소드
Integer num1 = Integer.valueOf(100);
Integer num2 = Integer.valueOf("200"); // 문자열을 전달받아도내부적으로 정수값으로 저장

// Integer num3 = num1.intValue() + num2.intValue(); // Integer객체에 저장된 정수값을 반환하는 메소드
System.out.println("num3 = " + num3.intValue());

*/


// Wrapper 클래스는 오토박싱과 오토언박싱 기능을 제공받아 객체를 생성하거나 사용 가능
// 오토박싱 (AutoBoxting) 원시형 리터럴() JVM이 자동으로 Wrapper 클래스의 객체로 생성하여 반환하는 기능
// 오토언박싱 : JVM Wrapper 클래스의 객체에 저장된 값을 원시형 리터럴로 반환하는 기능
 Integer num1 = 100;
        Integer num2 = 200;

        Integer num3 = num1 + num2;
        System.out.println("num3 = " + num3);


num3 = 300



        // Integer.valueOf(String s, int radix) : 매개변수로 전달받은 문자열을 원하는 진수의
        // 문자열을 정수값으로 변환하여 Intefer 객체에 저장하여 반환하는 메소드
        Integer num = Integer.valueOf("ABC", 16); // int num = 0 x ABC;
        // Integer 객체에 저장된 정수값을 반환받아 10진수로 출력
        System.out.println("num = " + num);

num = 2748
   
   

        Integer su = 50;
        System.out.println("su(10진수) = "+su);

        //Integer.toOctalString(int i) : 매개변수로 전달된 정수값을 8진수 형태의 문자열로 변환하여 반환하는 메소드
        System.out.println("su(8진수) = "+Integer.toOctalString(su));

        // Integer.toHexString(int i) : 매개변수로 전달된 정수값을 16진수 형태의 문자열로 변환하여 반환하는 메소드
        System.out.println("su(16진수) = "+Integer.toHexString(su));

        // Integer.toBinaryString(int i) : 매개변수로 전달된 정수값을 2진수 형태의 문자열로 변환하여 반환하는 메소드
        System.out.println("su(2진수) = "+Integer.toBinaryString(su));

        su=-50;
        System.out.println("su(2진수) = "+Integer.toBinaryString(su));

su(10진수) = 50
su(8진수) = 62
su(16진수) = 32
su(2진수) = 110010
su(2진수) = 11111111111111111111111111001110



        String str1 = "100";
        String str2 = "200";
        System.out.println("합계 = " + (str1+str2)); // 문자열 결합
        // Integer.parseInt(String s) 매개변수로 문자열을 전달받아 정수갑승로 변환하여 반환하는 메소드

        // > 정수값으로 변환되지 못하는 문자열이 전달된 경우 NumberFormatException 발생
        System.out.println("합계 = "+(Integer.parseInt(str1)+Integer.parseInt(str2)));

    }
}

합계 = 100200
합계 = 300

 


StringBufferApp

package xyz.itwill.lang;
// StringBuffer 클래스 : 문자열을 저장하기위한 클래스
// > StringBuffer 객체에 저장된 문자열의 문자 관련 메소드 제공
// > String 객체는 저장된 문자열을 조작하기 위한 메소드 제공X, 조작결과를 반환하는 메소드 제공
// > String 클래스보다 StringBuffer 클래스의 메소드가 문자열 처리 속도가 우수

 

public class StringBufferApp {
    public static void main(String[] args) {
        // StringBuffer 클래스는 new 연산자를 생성자를 호출하여 객체 생성
        StringBuffer sb = new StringBuffer("ABC");

        // StringBuffer.toString() - StringBuffer 객체에 저장된 문자열을 반환하는 메소드
        System.out.println("sb.toString() = " + sb.toString());
        // StringBuffer 객체가 저장된 참조변수를 출력할 경우 toString 메소드 자동 호출
        System.out.println("sb = " + sb);

        // StringBuffer 객체에 저장된 문자열을 반환받아 String 객체로 생성하여 참조변수 저장
        String str = sb.toString(); // StringBuffer 객체 >> String 객체

        System.out.println("str = " + str);
        
        
sb.toString() = ABC
sb = ABC
str = ABC


        // StringBuffer.append(Object o) - StringBuffer 객체에 저장된 문자열에 매개변수로
        // 전달받은 값을 추가하는 메소드
        // > String 객체에 저장된 문자열에 += 연산자를 사용한 효과와 동일
        sb.append("DEF");
        System.out.println("sb = " + sb); //ABCDEF

        str += "DEF";
        System.out.println("str = " + str);

sb = ABCDEF
str = ABCDEF



        // StringBuffer.insert(int index, Object o) : StringBuffer 객체에 저장된 문자열에
        // 매개변수로 전달받은 문자열을 원하는 위치(첨자)에 삽입하는 메소드
        sb.insert(4, "X");
        System.out.println("sb = " + sb); // ABCDXEF
        
sb = ABCDXEF


        // StringBuffer.deleteCharAt(int index) - StringBuffer객체에 저장된 문자열에서
        // 매개변수로 전달받은 취이의 문자를 제거하는 메소드
        sb.deleteCharAt(2);
        System.out.println("sb = " + sb); // ABCDXEF
        
sb = ABDXEF


        // StringBuffer.delete(int beginIndex, int endIndex) : StringBuffer 객체에 저장된
        // 문자열에서 매개변수로 전달받은 시작첨자부터 종료첨자 범위의 문자열을 제거하는 메소드
        sb.delete(4, 6);
        System.out.println("sb = "+sb); // ABDX
        
sb = ABDX


        // StringBuffer.reverse() : StringBuffer 객체에 저장된 문자열의 문자를 역순으로 나열되도록 저장하는 메소드
        sb.reverse();
        System.out.println("sb = "+sb); // XDBA
    }
}

sb = XDBA

 


SingleThreadApp

// 스레드 (Thread) - 프로세스의 명령을 실행하기 위한 최소의 작업단위 - 프로그램의 흐름
// 프로세스 (Process) - 메모리에 저장된 프로그램 - 중앙처리장치(CPU)에 의햐 실행되기 위한 명령

// 단일 스레드 프로그램
// > JVM에 의해 생성된 main 스레드를 이용하여 main() 메소드를 호출하여 명령 실행
// > main() 메소드가 종료되면 main스레드는 자동 소멸 - 프로그램 종료
package xyz.itwill.lang.thread;
public class SingleThreadApp {
    public static void main(String[] args) {

        /*
        System.out.println("SingleThreadAppp 클래스의 main() 메소드 시작");

        // Thread 클래스 : 스레드 관련 정보를 저장하여 스레드 관련 제어 기능을 메소드로 제공하기 위한 클래스
        // Thread.currentThread() : 형재 명령을 읽어 처리하는 스레드에 댜한 Thread객체를 반환하는 메소드
        // Thread.getName() : Thread객체에 저장된 스레드의 이름 (고유값)을 반환하는 메소드
        System.out.println("["+ Thread.currentThread().getName()
                + "] 스레드에 의해 main() 메소드의 명령 실행");


        // 객체를 생성하여 메소드를 호출한 경우 스레드가 메소드로 이동하여 메소드의 명령 실행
        // > 메소드의 명령을 모두 실행한 후 다시 현재 위치로 되돌아와 나머지 명령 실행
        new SingleThread().dispaly();//객체를 생성하여 직접 메소드 호출

        System.out.println("SingleThreadApp 클래스의 main() 메소드 종료");

         */

        for(char i='a';i<='z';i++) {
            System.out.print(i);

        }
    }
}

abcdefghijklmnopqrstuvwxyz

SingleThread 

package xyz.itwill.lang.thread;
public class SingleThread {
    public void dispaly() {
        /*
        System.out.println("SingleThread 클래스의 display() 메소드 시작");
        System.out.println("[" + Thread.currentThread().getName()
                + "] 스레드에 의해 SingleThread 클래스의 dispaly() 메소드 명령 실행");
        System.out.println("SingleThread 클래스의 disiplay() 메소드 종료");

         */
        for(char i='a';i<='z';i++) {
            System.out.print(i);
        }
    }
}

 


MultiThreadApp 

package xyz.itwill.lang.thread;

// 다중 스레드 프로그램
// > 프로그램 개발자가 직접 스레드를 생성하여 다수의 명령을 동시에 실행되도록 만든 프로그램
// > 프로그램의 모든 스레드가 소멸돼야만 프로그램 종료
// > GUI 프로그램 및 Web프로그램 등은 다중 스레드 프로그램으로 작성

// 프로그램 개발자가 스레드를 생성하여 명령을 실행하는 방법 -1 : Thread 클래스 이용
// 1.Thread 클래스를 상속받은 자식클래스 작성
// 2.Thread 클래스를 상속받은 자식클래스에서 run() 메소드 오버라이드 선언
// > run() 메소드에는 프로그램 개발자에 의해 생성된 스레드가 실행하기 위한 명령
// 3. Thread 클래스를 상속받은 자식클래스로 객체 생성 - Thread(부모클래스) 객체 생성
// 4. Thread 객체로 start() 메소드 호출 - Thread 객체를 이용하여 새로운 스레드 생성
// > 생성된 스레드는 자동으로 Thread객체의 run()메소드를 호출하여 run()메소드의 명령 실행

 

// 프로그램 개발자가 스레드를 생성하여 명령을 실행하는 방법 -2 : Runnable 인터페이스 이용
// > 클래스가 이미 다른 클래스를 상속받아 Thread 클래스를 상속받지 못하는 경우
// Runnable 인터페이스를 상속받아 새로운 스레드를 생성하기 위한 방법
// 1.Runnable 인터페이스를 상속받은 자식클래스 작성
// 2.Runnable 인터페이스를 상속받은 자식클래스에서 run() 메소드를 오버라이드 선언
// > run() 메소드에는 프로그램 개발자에 의해 생성된 스레드가 실행하기 위한 명령 작성
// 3.Thread 클래스로 Thread 객체를 생성 - Thread 클래스의 생성자 중 매개변수에 Runnable
// 인터페이스를 상속받은 자식클래스의 객체를 전달하여 Thread 객체를 생성하는 생성자 이용
// 4.Thread 객체로 start() 메소드 호출

 

public class MultiThreadApp {
    // JVM에 의해 main 스레드가 생성되어 main() 메소드를 호출하여 main() 메소드에 작성된 명령실행
    // > main()에 의해 전달된 예외는 JVM에 의해 자동으로 예외처리
    public static void main(String[] args) throws InterruptedException {
        /*
        // Thread 클래스로 직접 객체를 생성하여 start() 메소드 호출
        // > 새롭게 생성된 메소드는 Thread 객체에 선언된 명령이 없는 run() 메소드 호출 - 무의미
        Thread thread=new Thread();
		thread.start()
         */

        /*
        MultiThreadOne one = new MultiThreadOne();
        // Thread,start() : Thread객체로 새로운 스레드를 생성하기 위한 메소드
        // > 생성된 스레드는 자동으로 Thread객체의 run() 메소드(숨겨진 메소드)를 호출
        // > 자식클래스의 오버라이드 선언된 run()메소드가 호출되어 명령 실행
        one.start(); // 시작하게됨
        // 하나의 Thread객체는 하나의 스레드 생성만 가능
        // > Thread 객체를 사용하여 start() 메소드를 여러번 호출할 경우 IllegalThreadStarteEx
        // > 다중 스레드 프로그램에서 예외가 발생된 경우 예외가 발생된 스레드만 종료
        // one.start();
         */

        // Thread 객체를 사용하여 start() 메소드외에 다른 메소드를 호출하지 않을경우 참조변수에 객체를 저장하지 않고
        // 객체를 생성하여 직접 메소드 호출
        new MultiThreadOne().start();
        new MultiThreadOne().start();

        new Thread(new MultiThreadTwo()).start();

        for (char i = 'A'; i <= 'Z'; i++) {
            System.out.print(i);
            // Thread.sleep(long ms) - 스레드 객체가 잠/ 매개변수로 전달된 시간(ms)동안 스레드를 일시중지 하는 메소드
            // > 메소드에서 InterruptedException 전달 - 일반 예외이므로 예외처리를 하지않으면 에러 발생
            Thread.sleep(500); // 0.5초
        }
    }
}

aaA0bb1B2ccC3ddDe4eE5ffF6ggG7hhH8IiiJj9jKkkllLmMmNnnOooppPqqQrrRsSsTttuuUvvVWwwxxXyyYzzZ

 


 

MultiThreadOne 

package xyz.itwill.lang.thread;
public class MultiThreadOne extends Thread {

    public void run() {
        for (char i = 'a'; i <= 'z' ; i++) {
            System.out.print(i);
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

 


MultiThreadTwo

package xyz.itwill.lang.thread;
public class MultiThreadTwo implements Runnable {
    public void run() {
        for (char i = '0'; i <= '9'; i++) {
            System.out.print(i);
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();

            }
        }
    }
}

 


// 다중 스레드 프로그램의 문제점
// > 다수의 스레드가 run()메소드의 명령을 실행할 경우 같은 객체의 메소드를 호출하여
// 필드값(공유값)을 변경할 경우 잘못된 처리결과 발생 가능
// 해결법) 스레드 동기화를 이용하여 스레드 대한 메소드 호출 제어

// 스레드 동기화 : 스레드에 의헤 메소드 호출시 메소드의 모든 명령을 실행 하기전까지
// 다른 스레드로 메소드를 호출하지 목하도록 방지하는 기능
// > 다른 스레드가 이미 메소드를 호출하여 실행중인 경우 스레드를 일시 중지하여 기존 스레드의
// 메소드 처리가 끝난 후 일시 중지된 스레드가 실행되도록 락(Lock) 기능제공

// 스레드 동기화 처리방법
// 1. synchronized 키워드를 사용하여 메소드 선언 - 동기화 메소드 (Synchronized Method)
// 형식) 접근제한자 synchronized 반환형 메소드명(자료형 매개변수,...) { 명령; ... }
// 2. synchronized 키워드로 블럭을 설정하여 메소드 호출
// 형식) synchronized(객체) { 객체.메소드명(,...); ... }
// > synchronized 영역의 객체로 호출되는 모든 메소드는 동기화 처리되어 실행

Account

package xyz.itwill.lang.thread;
// 은행계좌정보(잔액)를 저장하기 위한 클래스 - 입금 및 출력 관련 메소드 작성
public class Account {
    private int balance;

    public Account() {
        // TODO Auto-generated constructor stub
    }

    public Account(int balance) {
        super();
        this.balance = balance;
    }

    public int getBalance() {
        return balance;
    }

    public void setBalance(int balance) {
        this.balance = balance;
    }

    // 입금 처리 메소드 - 매개변수로 입금자와 입금액을 전달받아 처리
    public void deposit(String name, int amount) {
        balance+=amount;
        System.out.println("[입금]"+name+"님이 "+amount+"원을 입금하여 잔액은 " + balance + "원입니다.");
    }

    // 출금 처리 메소드 - 매개변수로 출금자와 출금액을 전달받아 처리
    public void withDraw(String name, int amount) {
        if(balance < amount) {
            System.out.println("[에러]"+name+"님, 잔액이 "+balance+"원 남아 "+amount+"원을 출금할 수 없습니다.");
            return;
        }
        balance -= amount;
        System.out.println("[출금]"+name+"님에게 "+amount+"원이 출금되어 잔액은 "+balance+"원입니다.");

    }
}

 


 

AccountUser

package xyz.itwill.lang.thread;
public class AccountUser extends Thread {
    private Account account; // 은행계좌정보 - 포함관계
    private String userName; // 사용자명

    public AccountUser() {
        // TODO Auto-generated constructor stub
    }

    public AccountUser(Account account, String userName) {
        super();
        this.account = account;
        this.userName = userName;
    }

    public Account getAccount() {
        return account;
    }

    public void setAccount(Account account) {
        this.account = account;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public void run() {
        // 프로그램 개발자에 의해 생성된 스레드로 rub() 메소드를 호출하여 명령실행
        // > 은행계좌 사용자의 사용하는 은행계좌에 입금 처리하는 메소드 호출
        // account.deposit(userName, 5000);

        synchronized (account) {
            account.withDraw(userName, 5000);

        }
    }
}

 


AccountUserApp 

public class AccountUserApp {
    public static void main(String[] args) {
        // Account 클래스로 객체를 생성하여 저장 - 은행계좌 생성
        Account account = new Account(10000); // 잔액 10000원

        /*
        // 단일 스레드 (main)를 이용하여 AccountUser 클래스로  객체를 생성해 저장
        // > 은행계좌를 사용하는 사용자를 여러개 생성하여 같은 은행계좌를 사용하도록 설정
        AccountUser one = new AccountUser(account, "홍길동");
        AccountUser two = new AccountUser(account, "임꺽정");
        AccountUser three = new AccountUser(account, "전우치");

        // 단일 스레드(main)를 이용하여 모든 은행계좌 사용자를 이용한 은행계좌의 입금 처리
        one.getAccount().deposit(one.getUserName(), 5000); // 잔액 : 15000원
        two.getAccount().deposit(two.getUserName(), 5000); // 잔액 : 20000원
        three.getAccount().deposit(three.getUserName(), 5000); // 잔액 : 25000원
         */

        // 스레드를 여러개 생성하여 동시에 입금(출금) 처리
        // > 새로운 스레드를 생성하여 run() 메소드의 명령 실행 - 입금처리
        new AccountUser(account, "홍길동").start();
        new AccountUser(account, "임꺽정").start();
        new AccountUser(account, "전우치").start();
    }
}

[출금]홍길동님에게 5000원이 출금되어 잔액은 5000원입니다.
[출금]전우치님에게 5000원이 출금되어 잔액은 0원입니다.
[에러]임꺽정님, 잔액이 0원 남아 5000원을 출금할 수 없습니다.

 

 


 

ConsoleCaluelateApp (숙제)

//키보드로 사칙 연산식을 입력받아 연산결과를 계산하여 출력하는 프로그램 작성
//ex) 연산식 입력 >> 20 + 10
//    [결과]30
// > 입력 연산식에서 사용 가능한 연산자는 사칙 연산자(*,/,+,-)만 허용
// > 형식에 맞지 않는 연산식이 입력된 경우 에러 메세지 출력 후 프로그램 종료
// > 입력 연산식에 공백 입력이 가능하도록 처리
public class ConsoleCaluelateApp {
    public static void main(String[] args) {

    }
}