>  기사  >  Java  >  Java 스레드 풀에 대한 자세한 설명

Java 스레드 풀에 대한 자세한 설명

angryTom
angryTom앞으로
2019-11-26 15:05:413369검색

Java 스레드 풀에 대한 자세한 설명

스레드 풀 개요

1. 스레드 풀은 스레드를 관리하는 풀로, 스레드 생성 및 소멸로 인한 리소스 소모를 줄일 수 있습니다

스레드는 실제로 개체를 생성하는 객체이기 때문입니다. 클래스 로딩 과정에서 객체를 파괴하고 GC 가비지 수집 과정을 거치는 것은 모두 리소스 오버헤드를 필요로 합니다.

2. 스레드 풀에서 스레드를 가져오는 것에 비해 응답 속도가 향상됩니다.

3. 스레드를 모두 사용하면 다시 풀에 넣습니다. , 재사용 효과 달성

( 추천 영상 : java 영상 튜토리얼)

스레드 풀 실행

비유

코어 스레드를 회사 정규 직원과 비교

비코어 스레드를 비교 아웃소싱된 직원

블로킹 큐는 수요 풀과 비교됩니다

Submit 작업은 요청하는 것과 같습니다.

Java 스레드 풀에 대한 자세한 설명

정식 실행

public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize,long keepAliveTime,TimeUnit unit,
   BlockingQueue<Runnable> workQueue,
   ThreadFactory threadFactory,
   RejectedExecutionHandler handler)
corePoolSize     核心线程数
maximumPoolSize  线程池最大线程数
keepAliveTime    空闲线程存活时间
TimeUnit         线程空闲存活时间单位
workQueue        存放任务的阻塞队列
threadFactory    线程工厂
handler          饱和策略

● 스레드 풀에 남아 있는 코어 스레드 수가 다음과 같을 때 작업을 제출합니다. corePoolSize 스레드 수보다 적은 경우 스레드 풀은 제출된 작업을 처리하기 위해 코어 스레드를 생성합니다.

● 스레드 풀의 코어 스레드 수가 가득 찬 경우, 즉 스레드 수가 corePoolSize와 동일하면 새로 제출된 작업이 작업 대기열 workQueue에 들어가 실행을 위해 대기열에 추가됩니다.

● 스레드 풀에 남아 있는 스레드 수가 corePoolSize와 같고, 작업 큐 workQueue도 가득 찼을 때 스레드 수가 maximumPoolSize에 도달했는지, 즉 최대 스레드 수가 가득 찼는지 확인합니다. , 제출 작업을 실행하기 위한 비핵심 스레드를 생성합니다.

● 현재 스레드 수가 maximumPoolSize에 도달하고 새 작업이 오면 거부 정책이 직접 사용됩니다.

여러 가지 포화 전략

AbortPolicy         抛出一个异常,默认的
DiscardPolicy       直接丢弃任务
DiscardOldestPolicy 丢弃队列里最老的任务,将当前这个任务继续提交给线程池
CallerRunsPolicy    交给线程池调用所在的线程进行处理

스레드 풀 예외 처리

작업을 처리하기 위해 스레드 풀이 스레드를 호출할 때 발생하는 예외가 스레드 풀에 의해 포착될 수 있으므로 작업 실행이 인식되지 않을 수 있습니다. 따라서 스레드 풀 예외를 고려해야 합니다.

방법 1:

@Test
public void test1() throws Exception {
    ExecutorService executorService = Executors.newFixedThreadPool(5);
    for (int i = 0; i < 5; i++) {
        executorService.submit(new Runnable() {
            @Override
            public void run() {
                try {
                    System.out.println("name: " + Thread.currentThread().getName());
                    Object a = null;
                    System.out.println(a.hashCode());
                } catch (Exception e) {
                    System.out.println(e);
                }
            }
        });
    }
}

방법 2:

@Test
public void test2() throws Exception {
    ExecutorService executorService = Executors.newFixedThreadPool(5);
    for (int i = 0; i < 20; i++) {
        Future<?> future = executorService.submit(new Runnable() {
            @Override
            public void run() {
                System.out.println("name: " + Thread.currentThread().getName());
                Object a = null;
                System.out.println(a.hashCode());
            }
        });
        try {
            future.get();
        } catch (Exception e) {
            System.out.println(e);
        }
    }
}

스레드 풀의 작업 대기열

● ArrayBlockingQueue

● LinkedBlockingQueue

● 동기 대기열

● DelayQueue

●P riorityBlockingQueue

==ArrayBlockingQueue==

● 특정 용량의 배열 초기화

● 재진입 잠금 사용, 기본적으로 불공정 잠금 사용, 대기열 추가 및 대기열 제거가 동일한 잠금 공유, 상호 배제

● 제한된 설계, 용량이 가득 차면 요소를 삭제할 수 없음 요소가 있을 때까지 추가됨

● 사용 시 연속 메모리를 엽니다. 초기화 용량이 너무 크면 리소스 낭비가 발생하기 쉽습니다. 초기 용량이 너무 작으면 추가에 실패하기 쉽습니다.

== LinkedBlockingQueue==

● 연결된 목록 데이터 구조 사용

● 비연속 메모리 공간

● 두 개의 재진입 잠금을 사용하여 요소의 진입과 종료를 각각 제어하고 조건을 사용하여 스레드 사이에서 깨어나고 대기합니다

● 기본 구성 방식에서는 용량이 Integer.MAX_VALUE

== 동기 대기열==

● 내부 용량은 0

● 모든 삭제 작업은 삽입 작업을 기다려야 합니다

● 모든 삽입 작업은 삭제 작업을 기다려야 합니다

● 요소는 삽입 스레드와 제거 스레드가 있으면 삽입 스레드에서 제거 스레드로 빠르게 전달됩니다. 이 컨테이너는 채널과 동일하며 저장되지 않습니다. 다중 작업 대기열에서는 작업을 처리하는 가장 빠른 방법입니다.

==PriorityBlockingQueue==

● 무한한 디자인, 그러나 용량은 실제로 시스템 리소스에 따라 다름

● 요소 추가, 1개보다 많으면 우선 순위 정렬 입력

==DelayQueue==

● 무한한 디자인

● 추가 (put) 없이 차단 제거

● 요소에는 만료 시간이 있습니다

● 만료된 요소만 제거됩니다

일반적으로 사용되는 스레드 풀

● newFixedThreadPool(고정된 수의 스레드 스레드 풀)

● newCachedThreadPool (스레드를 캐시할 수 있는 스레드 풀)

● newSingleThreadExecutor(단일 스레드 풀)

● newScheduledThreadPool(예약 및 주기적인 실행을 위한 스레드 풀)

==newFixedThreadPool==

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

Features

1. 코어 스레드 수는 최대 스레드 수와 동일합니다

2. 소위 비유휴 시간이 없습니다. 즉, keepAliveTime은 0

3입니다. 차단 대기열은 무제한 대기열 LinkedBlockingQueue

작동 중입니다. 메커니즘:

Java 스레드 풀에 대한 자세한 설명● 작업 제출


● 스레드 수가 코어 스레드보다 적으면 코어 스레드를 생성하여 작업을 실행합니다.

● 스레드 수가 코어 스레드와 같은 경우 , LinkedBlockingQueue 차단 대기열에 작업을 추가하세요

● 如果线程执行完任务,去阻塞队列取任务,继续执行。

==newCachedThreadPool==

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

线程池特点

● 核心线程数为0

● 最大线程数为Integer.MAX_VALUE

● 阻塞队列是SynchronousQueue

● 非核心线程空闲存活时间为60秒

Java 스레드 풀에 대한 자세한 설명

工作机制:

● 提交任务

● 因为没有核心线程,所以任务直接加到SynchronousQueue队列。

● 判断是否有空闲线程,如果有,就去取出任务执行。

● 如果没有空闲线程,就新建一个线程执行。

● 执行完任务的线程,还可以存活60秒,如果在这期间,接到任务,可以继续活下去;否则,被销毁。

使用场景

用于并发执行大量短期的小任务。

使用SynchronousQueue作为工作队列,工作队列本身并不限制待执行的任务的数量。但此时需要限定线程池的最大大小为一个合理的有限值,而不是Integer.MAX_VALUE,否则可能导致线程池中的工作者线程的数量一直增加到系统资源所无法承受为止。

如果应用程序确实需要比较大的工作队列容量,而又想避免无界工作队列可能导致的问题,不妨考虑SynchronousQueue。SynchronousQueue实现上并不使用缓存空间

==newSingleThreadExecutor==

线程池特点

● 核心线程数为1

● 最大线程数也为1

● 阻塞队列是LinkedBlockingQueue

● keepAliveTime为0

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

工作机制

Java 스레드 풀에 대한 자세한 설명

● 提交任务

● 线程池是否有一条线程在,如果没有,新建线程执行任务

● 如果有,讲任务加到阻塞队列

● 当前的唯一线程,从队列取任务,执行完一个,再继续取,一个人(一条线程)夜以继日地干活。

使用场景

适用于串行执行任务的场景,一个任务一个任务的执行

==newScheduledThreadPool==

线程池特点

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

● 最大线程数为Integer.MAX_VALUE

● 阻塞队列是DelayedWorkQueue

● keepAliveTime为0

● scheduleAtFixedRate() :按某种速率周期执行

● scheduleWithFixedDelay():在某个延迟后执行

工作机制

● 添加一个任务

● 线程池中的线程从 DelayQueue 中取任务

● 线程从 DelayQueue 中获取 time 大于等于当前时间的task

● 执行完后修改这个 task 的 time 为下次被执行的时间

● 这个 task 放回DelayQueue队列中

scheduleWithFixedDelay

● 无论任务执行时间长短,都是当第一个任务执行完成之后,延迟指定时间再开始执行第二个任务

scheduleAtFixedRate

● 在任务执行时间小于间隔时间的情况下,程序以起始时间为准则,每隔指定时间执行一次,不受任务执行时间影响

● 当执行任务时间大于间隔时间,此方法不会重新开启一个新的任务进行执行,而是等待原有任务执行完成,马上开启下一个任务进行执行。此时,执行间隔时间已经被打乱

本文来自php中文网,java教程栏目,欢迎学习!

위 내용은 Java 스레드 풀에 대한 자세한 설명의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 cnblogs.com에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제