2020-10-16 TIL
3 minute read
스레드풀
스레드풀
- 스테이스리스는 요청이 들어와서 스레드를 만들 때마다 가비지가 생성된다.
- 이 방식의 문제점을 해결하기 위한 것이 스레드 풀이다.
- 스레드를 미리 만들어 놓고 사용하는 것
- 프로그램의 성능 저하를 방지한다.
- 매번 발생되는 작업을 병렬 처리하기 위해 스레드를 생성하고 수거하는데 따르는 부담이 프로그램의 전체적인 퍼포먼스를 저하시킬 수 있다.
- 다수의 사용자의 요청을 수용하고 빠르게 처리하고 대응할 수 있다.
- pooling 기법을 사용한다
- cross reference 문제 주의
- MyThread와 MyThreadPool 이 상호 참조 관계일 때
- 상호 참조를 하면 서로 변화가 있을 때마다 컴파일을 하기 때문에 무한 컴파일을 하게 된다.
- 현재 컴파일러는 성능이 좋기 때문에 한번만 컴파일을 하지만 객체 지향에서는 사용하지 않는 것이 좋은 방식이다.
- 이 문제점을 해결하기 위해서 ThreadPool을 만들어 MyThreadPool이 ThreadPool을 구현하도록 하고 MyThread는 ThreadPool을 사용하도록 한다.
- 이렇게 하면 상호 참조 관계를 해소할 수 있다.
- 자바로 만든 스레드는 전부 이 방식으로 돌아간다.
// 멀티 스레드 재사용 - Pooling 기법을 이용하여 생성된 객체를 재활용하기
package com.eomcs.concurrent.ex6;
import java.util.ArrayList;
import java.util.Scanner;
public class Exam0210 {
static class MyThread extends Thread {
ThreadPool pool;
int count;
public MyThread(String name, ThreadPool pool) {
super(name);
this.pool = pool;
}
public void setCount(int count) {
// 객체에 줄 값을 설정
this.count = count;
synchronized (this) {
// 객체에 알림을 주는 것
notify();
}
}
@Override
public void run() {
synchronized (this) {
try {
while (true) {
// 작업하라는 알림이 올 때까지 기다린다.
// not runnable 상태
wait();
// 알림이 오면 작업을 실행한다.
for (int i = count; i > 0; i--) {
System.out.printf("[%s] %d\n", getName(), i);
Thread.sleep(2000);
}
// 작업이 끝났으면 스레드풀로 돌아간다.
pool.add(this);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
// 상호 참조 관계를 해소하기 위해서
// 인터페이스를 준비했다.
interface ThreadPool {
Thread get();
void add(Thread obj);
}
static class MyThreadPool implements ThreadPool {
ArrayList<MyThread> list = new ArrayList<>();
public MyThreadPool() {
// 사용할 스레드 객체를 미리 생성한다.
// - 나중에 MyThread가 Pool로 다시 리턴될 수 있도록
// 스레드 객체를 생성할 때 Pool의 주소를 알려준다.
MyThread t1 = new MyThread("1번 스레드=>", this);
MyThread t2 = new MyThread("2번 스레드***>", this);
MyThread t3 = new MyThread("3번 스레드-->", this);
// 생성된 스레드를 컬렉션에 보관한다.
t1.start();
t2.start();
t3.start();
// 일단 무조건 스레드를 미리 실행해 놓는다.
list.add(t1);
list.add(t2);
list.add(t3);
}
// 스레드 풀에서 한 개의 스레드를 꺼낸다.
// 오버라이딩 할 때 하위 클래스로 바꾸는 것은 OK
// 먹을것 중에 라면을 주는 것
@Override
public MyThread get() {
if (list.size() > 0) { // 컬렉션에 남아있는 스레드가 있다면
return list.remove(0);
}
return null; // 없으면 null을 리턴한다.
// 현재 이 예제에서는 오직 3개의 스레드만 쓰도록 하였다.
}
// 스레드를 다 쓴 후에는 다시 스레드 풀에 돌려준다.
@Override
public void add(Thread t) {
list.add((MyThread) t);
}
}
public static void main(String[] args) {
// 스레드풀 준비!
MyThreadPool threadPool = new MyThreadPool();
Scanner keyScan = new Scanner(System.in);
while (true) {
System.out.print("카운트? ");
String str = keyScan.nextLine();
if (str.equals("quit")) {
break;
}
int count = Integer.parseInt(str);
// 스레드풀에서 스레드를 한 개 꺼낸다.
MyThread t = threadPool.get();
if (t == null) {
System.out.println("남는 스레드가 없습니다!");
continue;
}
// 스레드의 카운트를 설정한다. 그러면 카운트를 시작할 것이다.
t.setCount(count);
}
System.out.println("main 스레드 종료!");
keyScan.close();
}
}
이클립스에서 실행이 안될 때(Could not find of load)
- 빈 파일에서 컴파일 된 것이 있는지 확인
- 클린하고 재컴파일
- 그레이들 클린이클립스
- 그레이들 이클립스
시스템 개발
- 요구사항 수집
- 기존 시스템 분석 / 업무 분석
- UI prototype 제작
- 요구사항 분석
- 1) who?
- actor -> 시스템을 사용하는 사람 (예 : 은행원, 고객) / 프로세스 (예 : 타이머, 다른 시스템, ATM)
- Primary Actor -> 시스템을 사용
- Secondary Actor(Supplementery Actor) -> 시스템이 사용하는 외부 시스템
- 회원 -> sns 통합 조회 앱 -> 유튜브, 구글지도(외부 시스템)
- 회원이 primary, 외부 시스템이 secondary
- actor diagram
- Primary Actor
- Secondary Actor
- 구글 지도
- 네이버
- 페이스북
- 기상청
- 다음 우편번호
- 액터를 식별하는 것을 identify 한다고 한다.