Java 스레드 풀 전체 분석

6720 단어
개편: 왜 스레드 탱크를 사용합니까?
이 질문에 대답하기 전에 왜 다선정을 사용해야 하는지 생각해 볼까요?answer: 컴퓨터 프로세서의 처리 속도가 컴퓨터 메모리와 통신 서브시스템의 처리 속도를 크게 초과하기 때문에 단일 라인 상황에서 디스크 IO 조작을 하거나 네트워크 요청을 할 때 프로세서의 대부분 시간이 비어 있기 때문에 프로세서 자원의 낭비를 초래한다.또한 Android에서는 마스터 스레드는 UI 작업만 가능하며 시간이 많이 걸리면 하위 스레드에 배치해야 하며 그렇지 않으면 ANR이 발생할 수 있습니다.그래서 가능한 한'압착'프로세서의 효율을 위해 컴퓨터가 여러 개의 임무를 동시에 처리할 수 있고 임무의 집행 효율을 높일 수 있도록 자바는 다중 라인을 도입했다.
그런데 왜 스레드 탱크를 사용합니까?answer: 모든 jvm에 한정된 메모리 크기가 있습니다. 만약에 무제한으로 새로운 라인을 만들면 가상 기기의 빈번한 GC가 끊기고 무거운 것은 직접 oom로 가상 기기가 붕괴됩니다.또한 컴퓨터 프로세서의 병렬 처리 수량도 유한하기 때문에 일정 수량을 초과한 라인은 프로세서 처리의 효율을 가속화시키지 못한다.그래서 자바 가상 기기 환경의 녹색 안정을 유지하고 프로세서의 속도를 충분히 이용하며 라인을 통일적으로 관리하고 라인을 일정한 규칙에 따라 스케줄링 처리하기 위해 자바는 라인 탱크를 도입했다.
so: 어떻게 스레드 탱크를 만듭니까?
ThreadPoolExecutor 대상을 직접 사용하여 스레드 탱크 대상을 만들 수도 있고 자바에서 제공하는 네 가지 스레드 클래스를 통해 스레드 탱크 대상을 신속하게 만들 수도 있습니다.
코드:ThreadPoolExecutor를 통해 스레드 풀 생성
ExecutorService service = new ThreadPoolExecutor(3,3,
                10, TimeUnit.SECONDS,new LinkedBlockingDeque());

/**
     * Creates a new {@code ThreadPoolExecutor} with the given initial
     * parameters and default thread factory.
     *
     * @param corePoolSize the number of threads to keep in the pool, even
     *        if they are idle, unless {@code allowCoreThreadTimeOut} is set
     * @param maximumPoolSize the maximum number of threads to allow in the
     *        pool
     * @param keepAliveTime when the number of threads is greater than
     *        the core, this is the maximum time that excess idle threads
     *        will wait for new tasks before terminating.
     * @param unit the time unit for the {@code keepAliveTime} argument
     * @param workQueue the queue to use for holding tasks before they are
     *        executed.  This queue will hold only the {@code Runnable}
     *        tasks submitted by the {@code execute} method.
     * @param handler the handler to use when execution is blocked
     *        because the thread bounds and queue capacities are reached
     * @throws IllegalArgumentException if one of the following holds:
* {@code corePoolSize < 0}
* {@code keepAliveTime < 0}
* {@code maximumPoolSize <= 0}
* {@code maximumPoolSize < corePoolSize} * @throws NullPointerException if {@code workQueue} * or {@code handler} is null */ public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue workQueue, RejectedExecutionHandler handler) { this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, Executors.defaultThreadFactory(), handler); }

코어 Pool Size: 핵심 스레드 수, 기본적으로 스레드 탱크에 존재합니다.allow Core Thread Time Out이true로 설정되지 않으면 핵심 스레드도 빈 Keep AliveTime 이후에 회수됩니다.maximumPoolSize: 최대 스레드 수로 핵심 스레드와 비핵심 스레드를 포함하고 비핵심 스레드는keepAliveTime 이후 회수됩니다.keepAliveTime: 유휴 스레드 생존 시간.unit: 시간 단위(시분초 따위).workQueue: 작업 대기열입니다. 실행해야 할 Runnable 대상은 모두 이 대기열에 추가됩니다.threadFactory: 스레드를 만드는 공장 클래스입니다. 기본값DefaultThreadFactory입니다.handler: RejectedExecutionHandler 인터페이스 대상, 기본 AbortPolicy, 대기열이 한도에 도달했을 때 막히고 RejectedExecutionHandler의 RejectedExecution 방법을 실행합니다.
코드: Executors의 정적 방법으로 스레드 탱크 대상을 만듭니다.상기한 ThreadPoolExecutor 구조기에 대한 분석을 통해 우리는 아래의 네 가지 스레드 탱크의 특징을 잘 이해할 수 있다.1. FixedThreadPool, 핵심 스레드의 스레드 풀만 있고 빈 상태에서는 기본적으로 회수하지 않습니다.코드는 다음 그림과 같습니다.
ExecutorService service = Executors.newFixedThreadPool(3);

public static ExecutorService newFixedThreadPool(int nThreads) {
    return new ThreadPoolExecutor(nThreads, nThreads,
                                  0L, TimeUnit.MILLISECONDS,
                                  new LinkedBlockingQueue());
}

2. CachedThreadPool, 비핵심 스레드의 스레드 풀만 있고 스레드가 60초 이상 비어있으면 회수됩니다.코드는 다음 그림과 같습니다.
ExecutorService service = Executors.newCachedThreadPool();

public static ExecutorService newCachedThreadPool() {
      return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                  60L, TimeUnit.SECONDS,
                                  new SynchronousQueue());
 }

3. ScheduledThreadPool은 핵심 라인(corePoolsize가 지정)과 비핵심 라인이 있는 라인 탱크가 있고 비핵심 라인의 최대 값은 Integer이다.MAX_VALUE.코드는 다음 그림과 같습니다.
ExecutorService service = Executors.newScheduledThreadPool(3);

public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
    return new ScheduledThreadPoolExecutor(corePoolSize);
}

public ScheduledThreadPoolExecutor(int corePoolSize) {
    super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
          new DelayedWorkQueue());
 }

4.SingleThreadExecutor, 하나의 핵심 스레드만 있는 스레드 풀.코드는 다음과 같습니다.
ExecutorService service = Executors.newSingleThreadExecutor();

public static ExecutorService newSingleThreadExecutor() {
    return new FinalizableDelegatedExecutorService
        (new ThreadPoolExecutor(1, 1,
                                0L, TimeUnit.MILLISECONDS,
                                new LinkedBlockingQueue()));
}

마지막: 스레드 탱크의 대상을 사용하여 스레드 방법을 실행합니다.
Executor 서비스에서 제공하는 excute,submit 방법을 통해 루틴을 루틴 풀에 추가하여 실행합니다.
코드:excute (Runnable runnable) 를 통해 루틴 탱크에 Runnable 대상을 추가합니다
service.execute(new Runnable() {
      @Override
      public void run() {
             System.out.println("       ,  ");
      }
);

코드:submit(Callable callable)을 통해 스레드 풀에 Callable 객체 추가
Future task = service.submit(new Callable() {
      @Override
      public Integer call() throws Exception {
          System.out.println("        ,  ");
          return 66;
      }
});
//         task      66
task.get();

코드:submit (Runnable runnable) 을 통해 루틴 탱크에 Runnable 대상을 추가합니다
Future task1 = service.submit(new Runnable() {
      @Override
      public void run() {
          System.out.println("        ,  ");
      }
});
        
//         task      null
ask1.get();

코드:submit (Runnable runnable, T result) 을 통해 루틴 탱크에 Runnable 대상을 추가하고 반환값result를 지정합니다
Future task2 = service.submit(new Runnable() {
    @Override
    public void run() {
        System.out.println("        ,  ");
    }
  }, "hello");

 //         task      hello
 task2.get();

이렇게 하면 우리는 스레드 탱크를 만들고 사용할 수 있다. 잘 쓰지 못해도 좋아요를 눌러라, 허허.

좋은 웹페이지 즐겨찾기