스레드를 만드는 방법 2가지

1. Thread Class로 직접 생성, runnable interface 사용

- Runnable : 작업 스레드가 실행할 수 있는 코드를 가지고 있는 객체

- Runnable은 Interface Type -> 구현 객체 필요

- Runnable 내부에 있는 run() 메소드를 구현 클래스에서 run()을 Override를 통해 작업 스레드가 실행할 코드를 작성해야 한다.

- Runnable r = new 구현 객체 생성 후, new Thread(r) 구현 객체를 Thread 생성자의 매개 값으로 넣어주면 작업 스레드가 생성

- 생성된 스레드는 바로 실행되지 않고, thread.start()와 같이 start 메소드를 호출해야 실행된다.

- instance를 만들어서 객체를 Thread Class의 인자로 넣어준다.

 

 

2. Thread 하위 클래스로부터 생성

- Thread 하위 클래스로 작업 스레드를 정의하면서 작업 내용 포함

- Thread Class 상속 후, run()을 Override를 통해 작업 스레드가 실행할 코드를 작성한다.

- 생성된 객체에서 start() 메소드를 호출 -> run() 메소드 실행

- IS-A Relationship

- Java(단일 상속 지원)는 다중 상속 X -> Thread Class를 extends할 경우 제약이 생길 수 있다.

- Tightly Coupled 문제가 생길 수 있다.

- Main class가 실행 되면서, 메인 스레드가 생성

- Thread 객체를 생성하고, start() 메소드로 호출하면, 내부적으로 Thread stack을 할당받고, run() 호출


Thread의 이름 

- 메인 스레드 : main

- 직접 생성한 스레드 : Thread-n // n은 스레드의 번호

- setName(), getName()

- Thread.currentThread() : 객체의 참조가 없는 경우 사용

 

 

Thread 상태 전이도

 

스레드풀(ThreadPool)

- 스레드 개수가 늘어나게 되면, 생성과 스케줄링으로 CPU와 메모리 사용량이 늘어난다. -> 성능 저하

- 병렬 작업 폭증 -> 스레드 폭증 -> 성능 저하

- 스레드 풀을 사용해서 해결한다.

- 스레드 풀 : 스레드의 개수를 제한하고, 작업 큐(Queue)에 들어오는 작업들을 하나씩 맡아서 처리한다.

- ExecutorService Interface, Executors Class 사용

Thread 동기화

- 멀티 스레드에서, 여러 스레드가 하나의 객체를 공유해서 써야 하는 경우 사용

- 공유 자원의 문제가 발생 -> ex 예약 시스템

- 스레드가 사용 중인 객체를 다른 스레드가 변경할 수 없도록, 객체에 잠금을 걸어주어야 한다.

- 임계 영역(critical section)을 설정해서 문제 해결 -> lock 개념 도입

- 임게 영역 : 단 하나의 스레드만 실행할 수 있는 코드 영역

 

스레드 동기화 방법

- 임계 영역(critical section) : 공유 자원에 단 하나의 스레드만 접근하도록(하나의 프로세스에 속한 스레드만 가능)

- 뮤텍스(mutext) : 공유 자원에 단 하나의 스레드만 접근 가능하도록(서로 다른 프로세스에 속한 스레드도 가능)

- 이벤트(event) : 특정한 사건 발생을 다른 스레드에게 알린다.

- 세마포어(semaphore) : 한정된 개수를 가진 자원을 여러 스레드가 사용하려고 할 때 접근 제한

- 대기 기능 타이머(waitable timer) : 특정 시간이 되면 대기 중이던 스레드를 꺠운다.

 

 

 

동기화를 하지 않은 Code

- 스레드 2개가 동시에 실행되기 때문에 잔액이 마이너스가 나온다.

 

동기화 사용 synchronzied keywowrd

- 메소드 자체에 동기화를 하거나, 임의 영역을 설정해서 block으로 닫아주는 방법이 있다.

- 임의 영역을 설정해서 동기화 해주는 방식이 좀 더 사용하기 좋다.

- 공유 객체가 자기 자신인 경우 -> this

 

상태 전이도

- wait() : lock을 걸고 대기

 

notify() Method

- 스레드가 작업을 완료하면 notifiy를 호출해서 일시 정지 상태의 다른 스레드들을 실행 대기 상태로 옮긴다.

- 작업 완료된 스레드(자기 자신)는 wait() 메소드로 일시 정지 상태로 만든다.

- wait에서 대기하고 있는 스레드가 실행할 수 있는 상황이 되어서 block 해제

 

 

Java 고유 락(Intrinsic LocK)

  • 자바의 모든 객체는 lock을 갖고 있다.
  • synchronzied 블록은 Intrinsic lock(고유락)을 사용해서 스레드 접근을 제어한다.
  • synchronzied()
    • 1. 인자 값에 this 이용 : 여러 스레드가 들어와 서로 다른 block 호출해도 this를 사용해서 자기 자신에 lock을 걸어 기다려야 한다.
    • 2. 인자 값에 Object 이용 : block 마다 다른 Lock을 걸리게 해 효율적인 코드 작성 가능
  • structured lock(구조적 lock) : 고유 lock을 통한 동기화
  • reentarant lock(명시적 lock) : A획득 -> B획득 -> A해제 -> B해제를 가능하게 하기 위해서 사용
public class Counter{
    private Object lock = new Object(); // 모든 객체가 가능 (Lock이 있음)
    private int count;
    
    public int increase() {
        // 단계 (1)
        synchronized(lock){	// lock을 이용하여, count 변수에의 접근을 막음
            return ++count;
        }
        
        /* 
        단계 (2)
        synchronized(this) { // this도 객체이므로 lock으로 사용 가능
        	return ++count;
        }
        */
    }
    /*
    단계 (3)
    public synchronized int increase() {
    	return ++count;
    }
    */
}

Process(프로세스)
- 현재 실행중인 프로그램

- 프로세스는 최소한 1개 이상의 Thread(스레드)로 구성된다.

- 애플리케이션을 실행할 때, 운영체제로부터 실행에 필요한 메모리를 할당받아 애플리케이션의 코드를 실행하는 것

- 프로그램을 실행시키기 위해서는 OS로부터 자원(resource)를 할당 받아야 한다.

- 리소스(Code, Data, Stack, Heap) + Thread(여러 개) // Thread는 각각 Exception Stack을 별도로 가지고 있는 실행 흐름

 

프로세스 구성 요소 4가지

1. 코드(Code) 영역 : 프로그램의 코드

2. 데이터(Data) 영역 : 전역 변수 or 정적 변수의 할당 공간

3. 힙(Heap) 영역 : 메모리 동적 할당 공간

4. 스택(Stack) 영역  : 지역 변수 할당

 

Thread(스레드)

- 프로그램 내에서 실행되는 프로그램 제어 흐름(실행 단위)을 말한다.

- 스레드는 프로그램 코드를 한 줄씩 실행해준다.

- 스레드마다 독립적인 Stack을 따로 갖는다.

- Single Thread Process(싱글 스레드) : 스레드 1개

- Multi Thread Process(멀티 스레드) : 스레드 2개 이상

- Main Thread(메인 스레드)

 


싱글 스레드 vs 멀티 스레드

- 멀티 스레드는 싱글 스레드보다 효율적이다.

- 스레드의 개수는 제한이 없다.

 

- 스레드가 많을수록 좋은 것은 아니다.

-> 각각 스레드마다 스택이 할당되어야 하기 때문에

-> 스택 영역이 메소드를 호출할 때마다 모든 스레드에도 resource를 주어야 한다.

-> 자원이 부족하기 때문에 효율성 문제가 발생한다.

 

CPU Core(CPU 코어)

- 코어 : CPU 안에서 물리적인 연산(데이터 처리)를 담당하는 곳

- 코어는 한 가지 일만 한다.

- 과거의 코어 개수 1개 -> 최근 코어 개수 2개 이상

 

 

멀티 스레딩(Multi Threading)

- 장점 : 효율적인 처리 , 응답 속도 빠름

- 단점 : 어려운 프로그램, 공유 작업을 위한 동기화 필요 -> 교착상태(DeadLock)

- 동시성(Concurrency), 병렬성(Parallelism) 

- 코어보다 스레드 개수가 더 많을 경우, 우선순위 방식의 영향이 크지 않다.

 

동시성

- 단일 코어 내 멀티 스레드가 교차하면서 여러 Task를 수행함으로써, 동시에 실행되는 것 처럼 보인다.

- 많은 클라이언트의 요청을 처리할 수 있다.

 

병렬성

- 멀티코어 + 멀티 스레드 

- 같은 시간의 2개 이상의 일을 여러 프로세스가 동시에 수행하는 것

- 병렬적 수행을 빠르게 끝낼 수 있다.

 

동시성(Concurrency) 병렬성(Parallelism)
Single Core + 멀티 스레드 + Time-Slicing(시분할) Multi Core + 멀티 스레드
동시에 실행되는 것 처럼 보인다. 실제로 동시에 처리된다.
Context-Switching  
스레드 스케줄링 사용  

- 스레드 스케줄링 : 스레드를 어떤 순서에 의해 동시성으로 실행할 것인지 결정하는 것

- 스레드 스케줄링에 의해, 스레드는 번갈아가면서 run() 메소드 실행

- Java에서 우선순위(Priority), 순환 할당(Round-Robin) 스케줄링 사용

- Priority Scheduling : 우선순위가 높은 스레드 부터, 개발자가 코드로 제어 가능 // setPriority() 메소드로 우선순위 변경 가능

- Round-Robin Scheduling : Time Slice(시간 할당량)을 정해진 시간만큼 실행, JVM에 의해 제어

 

 

멀티 태스킹(Multi Tasking)

- 2가지 이상의 작업을 동시에 처리하는 것

- 멀티 태스킹 != 멀티 프로세스

- 하나의 프로세스도 멀티 태스킹이 가능하다 -> 멀티 스레드 이용

 

 

프로세스와 스레드의 개념

- 하나의 프로세스에서 오류가 발생해도 다른 프로세스에 영향 X

- 멀티 스레드에서 하나의 스레드에 오류가 발생하면 -> 프로세스가 종료될 수 있어 다른 스레드에 영향을 끼칠 수 있다.

- 스레드는 메소드를 실행하면서 JVM에 의해 생성된다.

- 자바에서 작업 스레드는 객체로 생성되기 때문에, Class가 필요하다.

- Thread class : main() 이외의 메소드. 메소드를 이용하여 Thread의 흐름을 제어하기 위한 클래스

- main() 메소드를 수행하기 위한 목적으로 제공되고, main Thread(또는 Daemon Thread)라고 불린다.

메인 스레드(Main Thread)

- main() 메소드를 실행하면서 시작된다.

- 작업 스레드들을 만들어서 병렬로 코드 실행 가능-> 멀티 스레드 생성 -> 멀티 태스킹 수행


Daemon Thread(데몬 스레드)

- 다른 일반 스레드의 보조적인 작업을 위해 사용

- 데몬 스레드는 (데몬)스레드를 파생시킨 일반 Thread가 모두 종료되면 같이 종료된다. 

- 사용 예시 : 가비지 컬렉터(GC), 자동 저장 기능..

- Thread.setDeamon(true) // 데몬 스레드 지정

- start() 호출 후에, setDeamon(true)를 호출하면 -> IllegalThreadStateException 발생

 


멀티 코어 프로세스 문제점

- 항상 메모리에 접근해서 값을 가져오는 것 보다, Core마다 독립적인 캐시 공간에 값을 저장해 두고 사용해서 접근 속도 최적화

- 하지만, 메모리 공간에 있는 값(실제 값)이 바뀌어도 캐시를 통해서 변경 전 값들을 가져오는 문제가 발생할 수 있다.

- volatile 키워드 사용 : 캐시에 저장된 값 X -> main memory 값 사용


스레드 그룹(Thread Group) 

- JVM 실행 시, system 스레드 그룹을 만들고 JVM 운영에 필요한 스레드들을 생성해서 system 스레드 그룹에 포함시킨다.

- 기본적으로 자신을 생성한 스레드와 같은 스레드 그룹에 속하게 된다.

스택 프레임(Stack Frame)

- 하나의 메소드에 필요한 메모리 덩어리

- 함수가 호출될때 스택에 매개 변수, 지역 변수, 복귀 주소가 스택에 저장된다.

- 백트래킹에 사용된다.

 

구성 요소

- 매개 변수

- 지역 변수

- 복귀 주소

 

스택 프레임 예제1 - 재귀함수를 이용해서 1~N까지의 수 더하기

public class Solution {
    public void DFS(int n){
        if(n==0) return;
        else {
            DFS(n-1);
            System.out.print(n+" ");
        }
    }

    public static void main(String[] args) {
        Solution T = new Solution();
        T.DFS(3);
    }
}

- DFS(3) 이 main 함수에서 실행

- DFS함수에서 DFS(3)이 5번째 줄에서 DFS(2) -> DFS(1)으로 넘어간다.

- DFS(0)에서 return으로 함수를 탈출하면서

- 스택에 쌓여있던 DFS(3), DFS(2), DFS(1)이 위에부터 pop으로 제거된다.

 

출력

- 1 2 3

 

스택 프레임 예제2 - 재귀함수를 이용해서 10진수 -> 2진수

public class Solution {
    public void DFS(int n){
        if(n==0) return;
        else {
            // System.out.print(n%2); 1101으로 출력됨
            DFS(n/2); // 스택프레임으로 인해서 1011으로 출력됨
        }
    }

    public static void main(String[] args) {
        Solution T = new Solution();
        T.DFS(11);
    }
}

이론 정리

연산자

  • 연산에 사용되는 표시나 기호
  • 피연산자 : 연산되는 데이터
  • 단항, 이항, 삼항 연산자 순서의 우선순위
  • 산술, 비교, 논리, 대입 연산자 순서의 우선순위
  • ++a 속도가 a=a+1 속도보다 빠르다.

String 타입

  • 참조형 타입

비트 연산자

  • 데이터를 bit 단위로 연산
  • 정수 타입만 가능
  • 비트 논리 연산자, 비트 이동 연산자

삼항 연산자

  • 세개의 피연산자를 필요로 하는 연산자
// 조건식 ? 값 또는 연산식(true) : 값 또는 연산식(false)
char grade = (score > 90) ? 'A' : ((score > 80) ? 'B' : 'C');

연습문제

[3-1] 다음 연산의 결과를 적으시오.

class Exercise3_1 {
    public static void main(String[] args){
        int x = 2;
        int y = 5;
        char c = 'A'; // 'A'의 문자 코드는 65
        
        System.out.println(1 + x << 33);
        System.out.println(y >= 5 || x < 0 && x > 2);
        System.out.println(y += 10 - x++);
        System.out.println(x+=2);
        System.out.println(!('A' <= c && c <= 'Z'));
        System.out.println('C'-c);
        System.out.println('5'-'0');
        System.out.println(c+1);
        System.out.println(++c);
        System.out.println(c++);
        System.out.println(c);
    }
}
  • 풀이
  • 1. 1+2 (3를 33만큼 왼쪽으로 이동 -> (32+1bit)1번만 이동 0011 -> 0110 = 6 2. true || false && false = false 논리연산자 &&가 ||보다 우선순위가 더 높다 true || true = true 3. 15-2++ = 13 4. (2++) + 2 = 5 5. !(true && true) = false 6. 67-65 = 2 7. 5 8. 66 9. B 10. B 11. C

[3-2] 아래의 코드는 사과를 담는데 필요한 바구니(버켓)의 수를 구하는 코드이다. 만일 사과의 수가 123개이고 하나의 바구니에는 10개의 사과를 담을 수 있다면, 13개의 바구니가 필요할 것이다. (1)에 알맞은 코드를 넣으시오.

class Exercise3_2 {
    public static void main(String[] args){
        int numOfApples = 123; // 사과의 개수
        int sizeOfBucket = 10; 
// 바구니의 크기(바구니에 담을 수 있는 사과의 개수)
        int numOfBucket = ( /*(1)*/ ); 
// 모든 사과를 담는데 필요한 바구니의 수
        
        System.out.println("필요한 바구니의 수 :"+numOfBucket);
    }
}
[실행결과]
13
  • 풀이
  • // numOfApples/sizeOfBucket+1; 반례 : 나머지가 0 인경우 ((numOfApples/sizeOfBucket)==0) ? numOfApples/sizeOfBucket : numOfApples/sizeOfBucket+1

[3-3] 아래는 변수 num의 값에 따라 ‘양수’, ‘음수’, ‘0’을 출력하는 코드이다. 삼항 연산자를 이용해서 (1)에 알맞은 코드를 넣으시오. (삼항 연산자 2번 사용)

class Exercise3_3 {
    public static void main(String[] args){
        int num = 10;
        System.out.println( /* (1) */ );
    }
}
[실행결과]
양수
  • 풀이
  • (num>0) ? "양수" : ((num<0) ? "음수" : '0')

[3-4] 아래는 변수 num의 값 중에서 백의 자리 이하를 버리는 코드이다. 만일 변수 num의 값이 ‘456’이라면 ‘400’이 되고, ‘111’이라면 ‘100’이 된다. (1)에 알맞은 코드를 넣으시오.

class Exercise3_4 {
    public static void main(String[] args){
        int num = 456;
        System.out.println( /* (1) */ );
    }
}
[실행결과]
400
  • 풀이
  • (num/100)*100

[3-5] 아래는 변수 num의 값 중에서 일의 자리 1로 바꾸는 코드이다. 만일 변수 num의 값이 ‘333’이라면 ‘331’이 되고, ‘777’이라면 ‘771’이 된다. (1)에 알맞은 코드를 넣으시오.

class Exercise3_5 {
    public static void main(String[] args){
        int num = 333;
        System.out.println( /* (1) */ );
    }
}
[실행결과]
331
  • 풀이
  • ((num/10)*10)+1

[3-6] 아래는 변수 num의 값보다 크면서도 가장 가까운 10의 배수에서 변수 num의 값을 뺀 나머지를 구하는 코드이다. 예를 들어, 24의 크면서도 가장 가까운 10의 배수는 30이다. 19의 경우 20이고, 81의 경우 90이 된다. 30에서 24를 뺀 나머지는 6이기 때문에 변수 num의 값이 24라면 6을 결과로 얻어야 한다. (1)에 알맞은 코드를 넣으시오.

class Exercise3_6 {
    public static void main(String[] args){
        int num = 24;
        System.out.println( /* (1) */ );
    }
}
[실행결과]
6
  • 풀이
  • (((num/10)+1)*10) - num

[3-7] 아래는 화씨(Fahrenheit)를 섭씨(Celsius)로 변환하는 코드이다. 변환공식이 ‘C’ = 5/9 x (F - 32)’ 라고 할 때, (1)에 알맞은 코드를 넣으시오. 단, 변환 결과값은 소수점 셋째자리에서 반올림해야한다. (Math.round()를 사용하지 않고 처리할 것)

class Exercise3_7 {
    public static void main(String[] args){
        int fahrenheit = 100;
        float celcius = ( /* (1) */ );

        System.out.println("Fahrenheit:"+fahrenheit);
        System.out.println("Celcius:"+celcius);
    }
}
[실행결과]
Fahrenheit:100
Celcius:37.78
  • 풀이
  • (int)((5/9f * (fahrenheit - 32))*100 + 0.5) / 100f; // 1. 37.77778 * 100 // 2. (1)+0.5 // 3. (int)(2) // 4. (3)/100f

[3-8] 아래 코드의 문제점을 수정해서 실행결과와 같은 결과를 얻도록 하시오.

class Exercise3_8 {
    public static void main(String[] args){
        byte a = 10;
        byte b = 20;
        byte c = a + b;

        char ch = 'A';
        ch = ch + 2;

        float f = 3/2;
        long l = 3000 * 3000 * 3000;

        float f2 = 0.1f;
        double d = 0.1;

        boolean result = d==f2;

        System.out.println("c="+c);
        System.out.println("ch="+ch);
        System.out.println("f="+f);
        System.out.println("l="+l);
        System.out.println("result="+result);
    }
}
[실행결과]
c=30
ch=C
f=1.5
l=27000000000
result=true
  • 풀이
  • byte c = (byte)(a + b); ch = (char)(ch + 2); float f = 3/2f; long l = 3000 * 3000 * 3000L; boolean result = (float)d==f2;

[3-9] 다음은 문자형 변수 ch가 영문자(대문자 또는 소문자)이거나 숫자일 때만 변수 b의 값이 true가 되도록 하는 코드이다. (1)에 알맞은 코드를 넣으시오.

class Exercise3_9 {
    public static void main(String[] args){
        char ch = 'z';
        boolean b = ( /* (1) */ );
        System.out.println(b);
    }
}
[실행결과]
true
  • 풀이
  • (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch >= '0' && ch <= '9')

[3-10] 다음은 대문자를 소문자로 변경하는 코드인데, 문자 ch에 저장된 문자가 대문자인 경우에만 소문자로 변경한다. 문자코드는 소문자가 대문자보다 32만큼 더 크다. 예를들어 ‘A’의 코드는 65이고, ‘a’의 코드는 97이다. (1)~(2)에 알맞은 코드를 넣으시오.

class Exercise3_10 {
    public static void main(String[] args){
        char ch = 'A';
        char lowerCase = ( /* (1) */ ) ? ( /* (2) */ ) : ch;

        System.out.println("ch:"+ch);
        System.out.println("ch to lowerCase:"+lowerCase);
    }
}
[실행결과]
ch:A
ch to lowerCase:a
  • 풀이
  • (ch >= 65 && ch < 97) ? (char)(ch+32)

이론 정리

변수(variable)

  • 값을 저장할 수 있는 메모리의 공간
  • 첫 번째 글자는 문자 or ‘&’, ‘_’ → 숫자, 예약어 불가능

리터럴(literal)

  • 소스 코드 내에서 직접 입력된 값
  • 정수, 실수, 문자, 논리 리터럴

데이터 타입

  • 기본 타입(primitive) : 정수, 실수, 문자, 논리 리터럴을 직접 저장하는 타입
    • 정수 타입(byte, char, short, int, long)
    • 실수 타입(float, double)
    • 논리 타입(boolean)

타입 변환

  • 자동(묵시적) 타입 변환
    • byte → char(음수X) : 불가능
  • 강제(명시적) 타입 변환 = 캐스팅(casting)
    • int → char : 불가능
    • 실수 → 정수 : 소수점이 버려진다.

연습문제

[2-1] 다음 표의 빈 칸에 8개의 기본형(primitive type)을 알맞은 자리에 넣으시오.

  • 풀이1byte2byte4byte8byte
    논리형 boolean      
    문자형   char    
    정수형 byte short int long
    실수형     float double

[2-2] 주민등록번호를 숫자로 저장하고자 한다. 이 값을 저장하기 위해서는 어떤 자료형(data type)을 선택해야 할까? regNo라는 이름의 변수를 선언하고 자신의 주민등록번호로 초기화 하는 한 줄의 코드를 적으시오.

  • 풀이
    long regNo = 1234561234567L; 
    // long타입 컴파일러에게 4byte가 아닌 8byte를 알려주기 위해 L를 뒤에 붙여준다.
    
  • 예시) 123456-1234567 = 13자리

[2-3] 다음의 문장에서 리터럴, 변수, 상수, 키워드를 적으시오.

int i = 100;
long l = 100L;
final float PI = 3.14f;
  • 리터럴 :
  • 변수 :
  • 키워드 :
  • 상수 :
  • 풀이
    • 리터럴 : 100, 100L, 3.14f
    • 변수 : i, l
    • 키워드 : int, long, final, float
    • 상수 : PI

[2-4] 다음 중 기본형(primitive type)이 아닌 것은?

  1. int
  2. Byte
  3. double
  4. boolean
  • 풀이
    • 기본형X : b(Byte) → byte
    • 기본형 : a(int), c(double), d(boolean)

[2-5] 다음 문장들의 출력결과를 적으세요. 오류가 있는 문장의 경우, 괄호 안에 ‘오류’ 라고 적으시오.

System.out.println("1" + "2") -> ( 12 )
System.out.println(true + "") -> ( true )
System.out.println('A' + 'B') -> ( 131 )
System.out.println('1' + 2) -> ( 51 )
System.out.println('1' + '2') -> ( 99 )
System.out.println('J' + "ava") -> ( Java )
System.out.println(true + null) -> ( 오류 )
  • 풀이
  • “1” + “2” = 12
  • ‘A’ + ‘B’ = 65 + 66 = 131
  • ‘1’ + ‘2’ = 49 + 50 = 99
  • true + null = 오류
    • 문자와 숫자가 같이 쓰일 때, 자동으로 아스키코드로 변환되서 사용된다.
  • ‘J’ + “ava” = Java
  • ‘1’ + 2 = 49 + 2 = 51
  • true + “” = true
  •  

[2-6] 다음 중 키워드가 아닌 것은?(모두 고르시오)

  1. if
  2. True
  3. NULL
  4. Class
  5. System
  • 풀이
    • True → true
    • NULL → null
    • Class → class

[2-7] 다음 중 변수의 이름으로 사용할 수 있는 것은? (모두 고르시오)

  1. $ystem
  2. channel#5
  3. 7eleven
  4. If
  5. 자바
  6. new
  7. $MAX_NUM
  8. hello@com
  • 풀이
    1. $ystem → 특수문자 $ 사용 가능
    2. channel#5 → 특수문자 # 불가능
    3. 7eleven → 앞에 숫자 불가능
    4. If → 가능
    5. 자바 → 한글 불가능
      • 이클립스에서는 한글 사용 가능!!!
    6. new → 예약어 불가능
    7. $MAX_NUM → 특수문자 $ 사용 가능
    8. hello@com → 특수문자 @ 불가능

[2-8] 참조형 변수(reference type)와 같은 크기의 기본형(primitive type)은? (모두 고르시오)

  1. int
  2. long
  3. short
  4. float
  5. double
  • 풀이
    • 참조형 변수는 64bit JVM을 사용하면 8byte : double
    • 32bit JVM을 사용하면 4byte : int, float

[2-9] 다음 중 형 변환을 생략할 수 있는 것은? (모두 고르시오)

byte b = 10;
char ch = 'A;
int i = 100;
long l = 1000L;

a. b = (byte)i;
b. ch = (char)b;
c. shrot s = (short)ch;
d. float f = (flaot)l;
e. i = (int)ch;
  • 풀이
    1. int(4) → byte(1) 크기가 작기 때문에 불가능
    2. byte(1) → char(2) 음수는 변환 불가능
    3. char(2) → short(2) 크기는 같지만, 음수 변환 불가능
    4. long(8) → float(4) 크기가 작아서 실수 생략 가능하므로 가능
    5. char(2) - int(4) 가능

[2-10] char 타입의 변수에 저장될 수 있는 정수 값의 범위는? (10진수로 적으시오)

  • 풀이
    • 0~65536 = 2^16-1

[2-11] 다음 중 변수를 잘못 초기화 한 것은? (모두 고르시오)

a. byte b = 256;
b. char c = '';
c. char answer = 'no';
d. float f = 3.14
e. double d = 1.4e3f;
  • 풀이
    1. byte : -128~127 불가능
    2. char : 한개의 문자가 아니라 불가능
    3. char : 두개의 문자 불가능
    4. float : 리터럴 뒤에 f가 오지 않아서 불가능

[2-12] 다음 중 main 메서드의 선언부로 알맞은 것은? (모두 고르시오)

a. public static void main(String[] args)
b. public static void main(String args[])
c. public static void main(String[] arv)
d. public void static main(String[] args)
e. static public void main(String[] args)
  • 풀이
    • a, b, c, e

[2-13] 다음 중 타입과 기본값이 잘못 연결된 것은? (모두 고르시오)

a. boolean - false
b. char - '\\u0000' // 16진수 저장
c. float - 0.0
d. int - 0
e. long - 0
f. String - ""
  • 풀이e. 리터럴 뒤에 L 생략되어 있어서 불가능
  • f. String의 기본 값은 null
  • c. 리터럴 뒤에 f 생략되어 있어서 불가능

'프로그래밍 > JAVA' 카테고리의 다른 글

[JAVA] 스택 프레임(Stack Frame)  (0) 2022.06.28
[자바의 정석] 연습문제 2. 연산자  (0) 2022.06.23
[JAVA] 자바 메모리 구조 - Heap, Stack, JVM, GC  (0) 2022.06.23
Ch06. 클래스  (0) 2022.01.02
Ch05. 참조 타입  (0) 2022.01.01

자바 실행 과정

- 프로그램 실행

- 자바 컴파일러 javac 에서 소스코드 .java 를 읽어서 바이트 코드 .class 로 변환한다.

- class loader로 class파일을 JVM으로 로딩

- class 파일들을 Execution engine으로 해석

- 해석된 바이트 코드를 Runtime Data areas에 배치되어 수행

 

JVM 

- java application을 class loader를 통해 읽어서 자바 API와 함께 실행한다.

- JAVA와 OS사이의 중개자 역할

- 자바 byte code를 실행할 수 있는 주체

- JAVA가 다른 언어에 비해 OS에 영향을 받지 않고 사용 가능하도록 해주는 장점이 있다.

- 다른 언어는 malloc 같은 메모리 할당을 하고 해제를 해줘야 하지만 자바는 GC를 이용해서 메모리 관리를 대신 해준다.

- 스택 기반의 가상머신(정적)

 

GC

- 동적으로 할당된 메모리 영역에서 사용하지 않는 영역을 GC가 할당 해제한다.

 

Stack

- 정적 메모리 할당 영역

- Primitive 타입 

- 메모리가 thread당 하나씩 할당

- 다른 thread끼리 stack 영역 접근 불가능 

 

Heap

- 동적 메모리 할당 영역

- Object 타입

- heap 영역의 Object를 가리키는 참조 변수가 Stack에 할당

- stack과 다르게 thread가 여러개 있어도, heap은 1개의 영역만 존재

 

STACK HEAP
빠른 접근 속도 느린 접근 속도
정적 메모리 할당 동적 메모리 할당
메모리 크기 제한 (OS에 영향) 메모리 크기 제한 X
Primitive type Object type
문제점 memory shortage 문제점 memory fragmentation
  ralloc(), new
선형적 계층적 구조

 

'프로그래밍 > JAVA' 카테고리의 다른 글

[자바의 정석] 연습문제 2. 연산자  (0) 2022.06.23
[자바의 정석] 연습문제 1.변수와 타입  (0) 2022.06.23
Ch06. 클래스  (0) 2022.01.02
Ch05. 참조 타입  (0) 2022.01.01
Ch04. 조건문과 반복문  (0) 2022.01.01

+ Recent posts