Java

[Java κ³ κΈ‰νŽΈ] μŠ€λ ˆλ“œ 생성과 μ‹€ν–‰

soogoori 2024. 9. 30. 10:19

ν”„λ‘œμ„ΈμŠ€μ™€ μŠ€λ ˆλ“œ

✳️ ν”„λ‘œμ„ΈμŠ€

  • 운영체제 μ•ˆμ—μ„œ μ‹€ν–‰ 쀑인 ν”„λ‘œκ·Έλž¨
  • μ‹€ν–‰ 쀑인 ν”„λ‘œκ·Έλž¨μ˜ μΈμŠ€ν„΄μŠ€
  • 각 ν”„λ‘œμ„ΈμŠ€λŠ” 독립적인 λ©”λͺ¨λ¦¬ 곡간을 κ°–κ³  있음 πŸ‘‰ ν”„λ‘œμ„ΈμŠ€κ°€ μ„œλ‘œμ˜ λ©”λͺ¨λ¦¬μ— 직접 μ ‘κ·Ό X
  • μš΄μ˜μ²΄μ œμ—μ„œ λ³„λ„μ˜ μž‘μ—… λ‹¨μœ„λ‘œ λΆ„λ¦¬ν•΄μ„œ 관리됨 
  • ν”„λ‘œμ„ΈμŠ€λŠ” ν•˜λ‚˜ μ΄μƒμ˜ μŠ€λ ˆλ“œλ₯Ό λ°˜λ“œμ‹œ 포함 

❇️ ν”„λ‘œμ„ΈμŠ€μ˜ λ©”λͺ¨λ¦¬ ꡬ성

  • μ½”λ“œ μ„Ήμ…˜ : μ‹€ν–‰ν•  ν”„λ‘œκ·Έλž¨μ˜ μ½”λ“œκ°€ μ €μž₯λ˜λŠ” λΆ€λΆ„
  • 데이터 μ„Ήμ…˜ : μ „μ—­ λ³€μˆ˜ 및 정적 λ³€μˆ˜κ°€ μ €μž₯λ˜λŠ” λΆ€λΆ„ (기타 λΆ€λΆ„)
  • νž™ : λ™μ μœΌλ‘œ ν• λ‹Ήλ˜λŠ” λ©”λͺ¨λ¦¬ μ˜μ—­
  • μŠ€νƒ : λ©”μ„œλ“œ 호좜 μ‹œ μƒμ„±λ˜λŠ” 지역 λ³€μˆ˜μ™€ λ°˜ν™˜ μ£Όμ†Œκ°€ μ €μž₯λ˜λŠ” μ˜μ—­ (μŠ€λ ˆλ“œμ— 포함)

 

✳️ μŠ€λ ˆλ“œ 

  • ν”„λ‘œμ„ΈμŠ€ λ‚΄μ—μ„œ μ‹€ν–‰λ˜λŠ” μž‘μ—…μ˜ λ‹¨μœ„
  • ν•œ ν”„λ‘œμ„ΈμŠ€ λ‚΄μ—μ„œ μ—¬λŸ¬ μŠ€λ ˆλ“œ 쑴재 κ°€λŠ₯ πŸ‘‰ ν”„λ‘œμ„ΈμŠ€κ°€ μ œκ³΅ν•˜λŠ” λ™μΌν•œ λ©”λͺ¨λ¦¬ 곡간 곡유

 

❇️ λ©”λͺ¨λ¦¬ ꡬ성

  • 곡유 λ©”λͺ¨λ¦¬ : 같은 ν”„λ‘œμ„ΈμŠ€μ˜ μ½”λ“œ μ„Ήμ…˜, 데이터 μ„Ήμ…˜, νž™(λ©”λͺ¨λ¦¬)은 ν”„λ‘œμ„ΈμŠ€ μ•ˆμ˜ λͺ¨λ“  μŠ€λ ˆλ“œκ°€ κ³΅μœ ν•¨
  • κ°œλ³„ μŠ€νƒ : 각 μŠ€λ ˆλ“œλŠ” μžμ‹ μ˜ μŠ€νƒμ„ κ°–κ³  있음

✳️ μžλ°” λ©”λͺ¨λ¦¬ ꡬ쑰

  • λ©”μ„œλ“œ μ˜μ—­ : ν”„λ‘œκ·Έλž¨μ„ μ‹€ν–‰ν•˜λŠ” 데 ν•„μš”ν•œ 곡톡 데이터 관리. ν”„λ‘œκ·Έλž¨μ˜ λͺ¨λ“  μ˜μ—­μ—μ„œ 곡유
    • 클래슀 정보 : 클래슀의 μ‹€ν–‰ μ½”λ“œ(λ°”μ΄νŠΈ μ½”λ“œ), ν•„λ“œ, λ©”μ„œλ“œ, μƒμ„±μž μ½”λ“œ λ“± λͺ¨λ“  μ‹€ν–‰ μ½”λ“œ
    • static μ˜μ—­ : static λ³€μˆ˜λ“€ 보관
    • λŸ°νƒ€μž„ μƒμˆ˜ ν’€ : ν”„λ‘œκ·Έλž¨μ„ μ‹€ν–‰ν•˜λŠ” 데 ν•„μš”ν•œ 곡톡 λ¦¬ν„°λŸ΄ μƒμˆ˜ 보관
  • μŠ€νƒ μ˜μ—­ : 지역 λ³€μˆ˜, 쀑간 μ—°μ‚° κ²°κ³Ό, λ©”μ„œλ“œ 호좜 정보 등을 포함
  • νž™ μ˜μ—­ : 객체(μΈμŠ€ν„΄μŠ€)와 배열이 μƒμ„±λ˜λŠ” μ˜μ—­. 가비지 μ»¬λ ‰μ…˜μ΄ μ΄λ£¨μ–΄μ§€λŠ” μ£Όμš” μ˜μ—­μ΄λ©° 더 이상 μ°Έμ‘°λ˜μ§€ μ•ŠλŠ” κ°μ²΄λŠ” 제거됨

 

 

 

μŠ€λ ˆλ“œ μƒμ„±ν•˜κΈ° - Thread 상속 

public class HelloThread extends Thread{
	@Override
    public void run(){
    	System.out.println(Thread.currentThread().getName() + " : run()");
    }
}
package thread.start;

public class HelloThreadMain {
	public static void main(String[] args) {
        System.out.println(Thread.currentThread().getName() + ": main() start");
        
        HelloThread helloThread = new HelloThread();
        System.out.println(Thread.currentThread().getName() + ": start() 호좜 μ „");
        
        helloThread.start();
        System.out.println(Thread.currentThread().getName() + ": start() 호좜 ν›„");
        
        System.out.println(Thread.currentThread().getName() + ": main() end");
    }
}

// >>> main: main() start
// >>> main: start() 호좜 μ „
// >>> main: start() 호좜 ν›„
// >>> Thread-0: run()
// >>> main: main() end

πŸ‘‰ start() λ₯Ό ν˜ΈμΆœν•˜λ©΄ HelloThread μŠ€λ ˆλ“œκ°€ run() λ©”μ„œλ“œλ₯Ό μ‹€ν–‰

πŸ‘‰ μŠ€λ ˆλ“œ κ°„ μ‹€ν–‰ μˆœμ„œλŠ” 보μž₯ λͺ»ν•¨ (= 좜λ ₯ μˆœμ„œ 일정 X)

β›” main μŠ€λ ˆλ“œκ°€ λ‹€λ₯Έ μŠ€λ ˆλ“œμ—κ²Œ μ‹€ν–‰ μ§€μ‹œ ν›„ λ©ˆμΆ”μ§€ μ•Šκ³  계속 μˆ˜ν–‰

 

  • main() λ©”μ„œλ“œλŠ” mainμ΄λΌλŠ” μ΄λ¦„μ˜ μŠ€λ ˆλ“œκ°€ μ‹€ν–‰ πŸ‘‰ ν”„λ‘œμ„ΈμŠ€κ°€ μž‘λ™ν•˜λ €λ©΄ μ΅œμ†Œν•œ ν•˜λ‚˜λŠ” μžˆμ–΄μ•Ό 함

 

  • HelloThread μŠ€λ ˆλ“œ 객체λ₯Ό μƒμ„±ν•œ ν›„ start() λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•˜λ©΄ μžλ°”λŠ” μŠ€λ ˆλ“œλ₯Ό μœ„ν•œ λ³„λ„μ˜ μŠ€νƒ 곡간 ν• λ‹Ή
  • μŠ€λ ˆλ“œμ— 이름을 λΆ€μ—¬ν•˜μ§€ μ•ŠμœΌλ©΄ μžλ°”λŠ” μŠ€λ ˆλ“œμ— Thread-0, Thread-1κ³Ό 같은 μž„μ˜μ˜ 이름 λΆ€μ—¬
  • Thread-0 μŠ€λ ˆλ“œλŠ” run()  λ©”μ„œλ“œμ˜ μŠ€νƒ ν”„λ ˆμž„μ„ μŠ€νƒμ— μ˜¬λ¦¬λ©΄μ„œ run() λ©”μ„œλ“œ μ‹œμž‘ πŸ‘‰ main μŠ€λ ˆλ“œκ°€ run() λ©”μ„œλ“œλ₯Ό μ‹€ν–‰ν•˜λŠ” 것이 μ•„λ‹˜ !
  • main μŠ€λ ˆλ“œλŠ” λ‹€λ₯Έ μŠ€λ ˆλ“œμ—κ²Œ 일을 μ‹œμž‘ν•˜λΌκ³  μ§€μ‹œλ§Œ ν•˜κ³  start() λ©”μ„œλ“œλ₯Ό λΉ μ Έλ‚˜μ˜΄ πŸ‘‰ 기닀리지 μ•ŠμŒ !
  • main μŠ€λ ˆλ“œμ™€ Thread-0 μŠ€λ ˆλ“œλŠ” λ™μ‹œμ— 싀행됨
🌟 μŠ€λ ˆλ“œ κ°„μ˜ μ‹€ν–‰ μˆœμ„œλŠ” μ–Όλ§ˆλ“ μ§€ λ‹¬λΌμ§ˆ 수 μžˆλ‹€ πŸ‘‰ λ©€ν‹° μŠ€λ ˆλ“œ 

 


λ§Œμ•½.. start() λŒ€μ‹  run() λ©”μ„œλ“œλ₯Ό 직접 ν˜ΈμΆœν•˜κ²Œ λœλ‹€λ©΄ ..? 

 

  • λ³„λ„μ˜ μŠ€λ ˆλ“œκ°€ run()을 μ‹€ν–‰ν•˜λŠ” 것이 μ•„λ‹ˆλΌ, main μŠ€λ ˆλ“œκ°€ run() λ©”μ„œλ“œλ₯Ό 호좜

✳️ 데λͺ¬ μŠ€λ ˆλ“œ

  • λ°±κ·ΈλΌμš΄λ“œμ—μ„œ 보쑰적인 μž‘μ—… μˆ˜ν–‰
  • λͺ¨λ“  user μŠ€λ ˆλ“œκ°€ μ’…λ£Œλ˜λ©΄ 데λͺ¬ μŠ€λ ˆλ“œλŠ” μžλ™μœΌλ‘œ μ’…λ£Œλ¨ 
  • ex) νŒŒμΌμ΄λ‚˜ λ©”λͺ¨λ¦¬ μ •λ¦¬ν•˜λŠ” μž‘μ—…
JVM은 데λͺ¬ μŠ€λ ˆλ“œμ˜ μ‹€ν–‰ μ™„λ£Œλ₯Ό 기닀리지 μ•Šκ³  μ’…λ£Œλ¨.
데λͺ¬ μŠ€λ ˆλ“œκ°€ μ•„λ‹Œ λͺ¨λ“  μŠ€λ ˆλ“œκ°€ μ’…λ£Œλ˜λ©΄ μžλ°” ν”„λ‘œκ·Έλž¨λ„ μ’…λ£Œλ¨

 

✳️ μ‚¬μš©μž μŠ€λ ˆλ“œ

  • ν”„λ‘œκ·Έλž¨μ˜ μ£Όμš” μž‘μ—… μˆ˜ν–‰
  • μž‘μ—…μ΄ μ™„λ£Œλ  λ•ŒκΉŒμ§€ 싀행됨
  • λͺ¨λ“  user μŠ€λ ˆλ“œκ°€ μ’…λ£Œλ˜λ©΄ JVM도 μ’…λ£Œλ¨

 

 

 

μŠ€λ ˆλ“œ μƒμ„±ν•˜κΈ° - Runnable μΈν„°νŽ˜μ΄μŠ€ κ΅¬ν˜„ν•˜κΈ°

Thread 클래슀λ₯Ό μƒμ†ν•˜λŠ” 방식보닀 Runnable μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•˜λŠ” 것이 더 λ‚˜μŒ !
public interface Runnable{
	void run();
}
public class HelloRunnable implements Runnable{
	
    @Override
    public void run(){
    	System.out.println(Thread.currentThread().getName() + ": run()");
    }
}
public class HelloRunnableMain{
	
    public static void main(String[] args){
    	System.out.println(Thread.currentThread().getName() + ": main() start");
        
        HelloRunnable runnable = new HelloRunnable();
        Thread thread = new Thread(runnable);
        thread.start();
        
        System.out.println(Thread.currentThread().getName() + " : main() end");
    }
}
// >>>  main: main() start
// >>>  main: main() end
// >>>  Thread-0: run()
  • μŠ€λ ˆλ“œμ™€ ν•΄λ‹Ή μŠ€λ ˆλ“œκ°€ μ‹€ν–‰ν•  μž‘μ—…μ΄ μ„œλ‘œ λΆ„λ¦¬λ˜μ–΄μžˆμŒ
  • μŠ€λ ˆλ“œ 객체λ₯Ό 생성할 λ•Œ μ‹€ν–‰ν•  μž‘μ—…μ„ μƒμ„±μžλ‘œ 전달

✳️ Thread 상속 vs Runnable κ΅¬ν˜„ 

  • Thread 클래슀 상속 방식
    • Thread 클래슀λ₯Ό 상속받아 run() λ©”μ„œλ“œλ§Œ μž¬μ •μ˜ν•˜λ©΄ 됨
    • μƒμ†μ˜ μ œν•œ 있음 πŸ‘‰ μžλ°”λŠ” 단일 μƒμ†λ§Œ ν—ˆμš©ν•˜λ―€λ‘œ 이미 λ‹€λ₯Έ 클래슀λ₯Ό 상속받고 μžˆλŠ” 경우 Thread 상속 λΆˆκ°€
    • μœ μ—°μ„± 떨어짐
  • Runnable μΈν„°νŽ˜μ΄μŠ€ κ΅¬ν˜„ 방식
    • μƒμ†μ˜ μžμœ λ‘œμ›€
    • μŠ€λ ˆλ“œμ™€ μ‹€ν–‰ν•  μž‘μ—…μ„ λΆ„λ¦¬ν•˜μ—¬ μ½”λ“œμ˜ 가독성 λ†’μž„
    • μ—¬λŸ¬ μŠ€λ ˆλ“œκ°€ λ™μΌν•œ Runnable 객체λ₯Ό κ³΅μœ ν•  수 μžˆμ–΄ μžμ› 관리 효율적
    • μ½”λ“œκ°€ μ•½κ°„ λ³΅μž‘ν•΄μ§ πŸ‘‰ Runnable 객체λ₯Ό μƒμ„±ν•˜κ³  이λ₯Ό Thread에 μ „λ‹¬ν•˜λŠ” κ³Όμ • μΆ”κ°€ 

 

 

 

λ©€ν‹°μŠ€λ ˆλ“œ ν”„λ‘œκ·Έλž¨ μ˜ˆμ‹œ

✳️ Thread 상속

1. `Thread` 클래슀λ₯Ό 상속받은 `CounterThread` λΌλŠ” μŠ€λ ˆλ“œ 클래슀λ₯Ό λ§Œλ“€κΈ°
2. 이 μŠ€λ ˆλ“œλŠ” 1λΆ€ν„° 5κΉŒμ§€μ˜ 숫자λ₯Ό 1초 κ°„κ²©μœΌλ‘œ 좜λ ₯ν•΄μ•Ό 함.  `log()` κΈ°λŠ₯을 μ‚¬μš©ν•΄μ„œ 좜λ ₯
3. `main()` λ©”μ„œλ“œμ—μ„œ `CounterThread` μŠ€λ ˆλ“œ 클래슀λ₯Ό λ§Œλ“€κ³  μ‹€ν–‰

 

public class StartTest1Main {
	public static void main(String[] args){
    	CounterThread thread = new CounterThread();
        thread.start();
    }
    
    static class CounterThread extends Thread {
    	
        @Override
        public void run(){
        	for(int i=1; i<=5; i++){
            	log("value : " + i);
                try{
                	Thread.sleep(1000);
                }catch(InterruptedException e){
                	throw new RuntimeException(e);
                }
            }
        }
    }
}

 

✳️ Runnable κ΅¬ν˜„

1. `CounterRunnable` μ΄λΌλŠ” μ΄λ¦„μ˜ 클래슀λ₯Ό λ§Œλ“€κΈ°. 이 ν΄λž˜μŠ€λŠ” `Runnable` μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•΄μ•Ό 함
2. `CounterRunnable` 은 1λΆ€ν„° 5κΉŒμ§€μ˜ 숫자λ₯Ό 1초 κ°„κ²©μœΌλ‘œ 좜λ ₯. `log()` κΈ°λŠ₯을 μ‚¬μš©ν•΄μ„œ 좜λ ₯.
3. `main` λ©”μ„œλ“œμ—μ„œ `CounterRunnable` 의 μΈμŠ€ν„΄μŠ€λ₯Ό μ΄μš©ν•΄μ„œ `Thread` λ₯Ό μƒμ„±ν•˜κ³  μ‹€ν–‰.
4. μŠ€λ ˆλ“œμ˜ 이름은 "counter"둜 지정.

 

public class StartTest2Main{
	public static void main(String[] args){
    	Thread thread = new Thread(new CounterRunnable(), "counter");
        thread.start();
    }
    
    static class CounterRunnable implements Runnable{
    	public void run(){
        	for(int i=1; i<=5; i++){
            	log("value : " + i);
                try{
                	Thread.sleep(1000);
                }catch (InterruptedException e){
                	e.printStackTrace();
                }
            }
        }
    }
}

 

✳️ Runnable 읡λͺ… 클래슀 κ΅¬ν˜„

public class StartTest3Main{
	public static void main(String[] args){
    	Runnable runnable = new Runnable(){
        	@Override
            public void run(){
            	for(int i=1; i<=5; i++){
                	log("value : " + i);
                    try{
                    	Thread.sleep(1000);
                    }catch (InterruptedException e){
                    	e.printStackTrace();
                    }
                }
            }
        };
        
        Thread thread = new Thread(runnable, "counter");
        thread.start();
    }
}

 

✳️ μ—¬λŸ¬ μŠ€λ ˆλ“œ μ‚¬μš©

 Thread-A , Thread-B 두 μŠ€λ ˆλ“œλ₯Ό λ§Œλ“€κΈ°
Thread-A λŠ” 1μ΄ˆμ— ν•œ λ²ˆμ”© "A"λ₯Ό 좜λ ₯
Thread-B λŠ” 0.5μ΄ˆμ— ν•œ λ²ˆμ”© "B"λ₯Ό 좜λ ₯
κ°•μ œ μ’…λ£Œν•  λ•ŒκΉŒμ§€ 계속 μ‹€ν–‰.
public class StartTest4Main{

	public static void main(String[] args){
    	Thread threadA = new Thread(new PrintWork("A", 1000), "Thread-A");
        Thread threadB = new Thread(new PrintWork("B", 500), "Thread-B");
        
        threadA.start();
		threadB.start();
    }
    
    static class PrintWork implements Runnable{
		private String content;
        private int sleepMs;
        
        public PrintWork(String content, int sleepMs){
        	this.content = content;
            this.sleepMs = sleepMs;
        }
        
        @Override
        public void run(){
        	while(true){
            	log(content);
                try {
					Thread.sleep(sleepMs);
                } catch (InterruptedException e) {
                	throw new RuntimeException(e);
                }
            }
        }
	}	
}