ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 29. 멀티스레드
    개발자 수업/Java 2021. 10. 22. 17:19

    1. 프로세스(process)
        1) 프로그램 ---실행---> 프로세스
        2) 프로그램이 실행되면 OS(Operating System)로부터 메모리를 할당받아 프로세스 상태가 됨
        3) 하나의 프로그램이 여러 개의 프로세스를 만들기도 함

    2. 멀티 태스킹(multy tasking)
        1) 통상 두 가지 이상의 작업을 동시에 처리하는 것을 칭함
        2) 구현 방법
            - 멀티 프로세스
                - 독립적 프로그램을 여러 번 실행하고 작업을 처리하는 것
            - 멀티 스레드
                - 하나의 프로그램을 실행하여, 내부적으로 여러 가지 작업을 처리하는 것
                    ex) 카카오톡 - 채팅 스레드, 파일 전송 스레드 등
                - 소프트웨어 병행 작업 처리를 위해 multy thread를 사용함

    3. 스레드(thread)
        1) 하나의 프로세스는 하나 이상의 thread를 가지게 됨
            - 하나의 프로세스에는 여러 개의 스레드 생성 가능
            - 스레드들은 동시에 실행 가능
            - 프로세스 안에 있으므로, 프로세스의 데이터를 모두 접근 가능
        2) 실제 작업을 수행하는 단위
        3) Light Weight Process라고도 함
        4) 프로세스 간에는 각 프로세스의 데이터 접근이 불가
        
    4. Thread 장점
        1) 사용자에 대한 응답성 향상
            - ThreadA : 특정 작업
              ThreadB : 사용자와 커뮤니케이션
        2) 자원 공유 효율
        3) 작업이 분리되어 코드가 간결(작성하기 나름)

    5. Thread 단점
        1) 스레드 중 한 스레드만 문제가 있어도 전체 프로세스가 영향을 받음
        2) 스레드를 많이 생성하면 모든 스레드를 스케쥴링해야 하므로 Context Switching이 많이 일어나 성능 저하

    6. 메인 스레드 vs 작업 스레드 
        1) 메인 스레드는 작업 스레드들을 만들어서 병렬로 코드를 실행할 수 있으며 이것이 곧 멀티 태스킹을 수행하는 것임

    /*
     * 메인 스레드(main thread)
     * 	1) 모든 자바 프로그램은 JVM의 메인스레드가 main()을 실행하면서 시작함
     * 	2) main()의 첫 코드부터 아래로 순차적으로 실행함
     * 	3) 실행 종료 조건은 마지막 코드를 실행하거나, return문을 만나면 종료함
     */
    public class BeepSoundTest {
    	public static void main(String[] args) {
    		//현재 실행중인 스레드명 출력
    		System.out.println(Thread.currentThread().getName());
    		
    		for(int i=0; i<5; i++) {
    			System.out.println("for문을 실행하는 스레드 이름 : " + Thread.currentThread().getName());
    		}
    		
    		for(int i=0; i<5; i++) {
    			System.out.println("삐웅~");
    			System.out.println("for문을 실행하는 스레드 이름2 : " + Thread.currentThread().getName());
    		}
    		
    	}
    }

    package kr.co.ezenac.multythread01;
    
    public class ThreadTest {
    	
    	//main()은 JVM이 실행함
    	public static void main(String[] args) {
    		
    		//방법1) 구현객체 runnable 대입
    //		Runnable runnable = new Ezen();
    //		Thread thread = new Thread(runnable);
    //		thread.start();
    		
    		//방법2) 익명내부객체
    //		Thread thread2 = new Thread(new Runnable() {
    //			
    //			@Override
    //			public void run() {
    //				for(int i=0; i<5; i++) {
    //					System.out.println("main for문을 실행하는 스레드 이름 : " + Thread.currentThread().getName());
    //					
    //					try {
    //						Thread.sleep(500);
    //					} catch (InterruptedException e) {
    //						e.printStackTrace();
    //					}
    //				}
    //			}
    //		});
    //		thread2.start();
    		
    		//방법3) 람다식(함수적 인터페이스)
    		Thread thread3 = new Thread(() -> {
    			for(int i=0; i<5; i++) {
    				System.out.println("main for문을 실행하는 스레드 이름 : " + Thread.currentThread().getName());
    				
    				try {
    					Thread.sleep(500);
    				} catch (InterruptedException e) {
    					e.printStackTrace();
    				}
    			}
    		});
    		thread3.start();
    	}		
    }
    //Runnable 인터페이스를 직접 구현함
    public class Ezen implements Runnable {
    
    	@Override
    	public void run() {
    		//스레드가 실행할 코드
    		for(int i=0; i<5; i++) {
    			System.out.println("Ezen for문을 실행하는 스레드 이름 : " + Thread.currentThread().getName());
    			
    			try {
    				Thread.sleep(500);
    			} catch (InterruptedException e) {
    				e.printStackTrace();
    			}
    		}
    	}
    
    }

    /*
     * Thread 구현하기
     * 	- 자바 Thread 클래스로부터 상속받아 구현
     */
    public class TimerThread extends Thread {
    	
    	@Override
    	public void run() {
    		for(int i=10; i>0; i--) {
    			System.out.println("남은 시간 : " + i);
    			try {
    				Thread.sleep(1000);
    			} catch (InterruptedException e) {
    				e.printStackTrace();
    			}
    		}
    	}
    }
    import javax.swing.JOptionPane;
    
    public class TimerThreadTest {
    	public static void main(String[] args) throws InterruptedException {
    		
    		Thread thread = new TimerThread();
    		thread.start();
    		
    		String input = JOptionPane.showInputDialog("10초 안에 값을 입력하세요.");
    		
    		if(input != null) {
    			System.out.println("입력 값 : " + input);
    			System.exit(0);
    		} else {
    			Thread.sleep(10000);	//10초를 대기함
    			System.out.println("입력하지 못했습니다.");
    			System.exit(0);
    		}
    	}
    }



    7. 프로세스 종료
        1) 싱글 스레드 : 메인 스레드가 종료하면 프로세스도 함께 종료됨
        2) 멀티 스레드 : 실행 중인 스레드가 하나라도 있다면 프로세스는 종료되지 않음
            - 메인 스레드가 작업 스레드보다 먼저 종료되더라도 작업 스레드가 계속 실행 중이라면 프로세스는 종료되지 않음

    8. 작업 스레드의 이름
        1) 메인 스레드 이름 : main <== JVM이 생성과 동시에 부여함
        2) 작업 스레드 이름(자동 설정) : Thread-n
        3) 작업 스레드 이름 변경 : thread.setName("스레드 이름");
        4) 코드 실행하는 현재 실행 중인 스레드 객체의 참조 얻기
           Thread thread = Thread.currentThread();
           thread.getName();
        5) 개발할 때 디버깅 과정에서 사용함

    9. 동시성과 병렬성
        1) 동시성(Concurrency)
            - 하나의 CPU core가 스레드를 실행했다가 실행대기 시켰다가 다른 스레드를 진행시키는 방법임
            - 멀티작업 위해 하나의 코어에서 멀티 스레드가 번갈아가며 실행하는 성질
        2) 병렬성(Parallelism)
            - 멀티 개의 코어가 하나씩 스레드를 맡아서 독립적으로 진행하여 방해를 받지 않는 특성이 있음
            - 멀티작업 위해 멀티 코어에서 개별 스레드를 동시에 실행하는 성질

    10. 스레드 우선 순위
        1) 스레드들이 동시성을 가질 경우 우선적으로 실행할 수 있는 순위
        2) 우선 순위는 1(낮음)부터 10(높음)까지 부여함
            - 모든 스레드의 우선 순위는 5임

    public class ThreadEzenac extends Thread {
    	
    	public ThreadEzenac() {
    		this.setName("ThreadEzenac");	//스레드 이름 지정
    	}
    	
    	@Override
    	public void run() {
    		System.out.println("[현재 실행 중인 스레드 이름] : " + this.getName());
    		for(int i=0; i<5; i++) {
    			System.out.println(this.getName() + "가 출력한 내용임 - " + i);
    			try {
    				Thread.sleep(100);
    			} catch (InterruptedException e) {
    				e.printStackTrace();
    			}
    		}
    	}
    }
    public class ThreadGangnamS extends Thread {
    	
    	public ThreadGangnamS() {
    		this.setName("ThreadGangnamS");
    	}
    	
    	@Override
    	public void run() {
    		System.out.println("[현재 실행 중인 스레드 이름] : " + this.getName());
    		for(int i=0; i<5; i++) {
    			System.out.println(this.getName() + "가 출력한 내용임 - " + i);
    			try {
    				Thread.sleep(100);
    			} catch (InterruptedException e) {
    				e.printStackTrace();
    			}
    		}
    	}
    }
    public class ThreadNameTest {
    	public static void main(String[] args) {
    		
    		Thread thread = Thread.currentThread();
    		System.out.println("[프로그램 시작 스레드 명] : " + thread.getName());
    		
    		Thread ezenac = new ThreadEzenac();
    		ezenac.start();
    		
    		System.out.println("[ThreadEzenac을 생성한 스레드 이름] : " + Thread.currentThread().getName());
    		System.out.println("main스레드가 ThreadEzenac의 이름을 가져온 것 : " + ezenac.getName());
    	
    		Thread gangnam = new ThreadGangnamS();
    		gangnam.start();
    		System.out.println("main스레드가 ThreadEzenac의 이름을 가져온 것 : " + gangnam.getName());
    	}
    }

    public class CalcThread extends Thread {
    	
    	long sum;
    	
    	public CalcThread(String name) {
    		this.setName(name);
    	}
    	
    	@Override
    	public void run() {
    		for(int i=0; i<2000000; i++) {
    			sum += i;
    		}
    		System.out.println("[작업 완료 스레드] : " + this.getName());
    		System.out.println("[합계] : " + this.sum );
    	}
    }
    /*
     * 우선순위를 10으로 설정했으나 작업을 마치는 빈도가 높을 뿐이지
     * 무조건 100% 먼저 끝낸다는 보장은 없음
     */
    public class PriorityTest {
    	public static void main(String[] args) {
    		
    		Thread thread = Thread.currentThread();
    		System.out.println(thread.getName() + " : " + thread.getPriority());
    		
    		for(int i=1; i<=20; i++) {
    			Thread thread2 = new CalcThread("eZenThread : " + i);
    			
    			if(i != 20) {
    				thread2.setPriority(Thread.MIN_PRIORITY);
    			} else {
    				thread2.setPriority(Thread.MAX_PRIORITY);
    			}
    			
    			thread2.start();
    		}
    	}
    }

    '개발자 수업 > Java' 카테고리의 다른 글

    31. 멀티스레드2  (0) 2021.10.25
    30. Review  (0) 2021.10.25
    28. IO입출력  (0) 2021.10.20
    27. 예외처리  (0) 2021.10.20
    26. 스트림  (0) 2021.10.19

    댓글