예술 자바 병행 프로그래밍 - 독서 요약

요약 및 유도 "의 분야에서 자바 동시성"을 읽은 후. 당신은 질문이있는 경우에, 저를 수정하시기 바랍니다.

제 1 장 동시 프로그래밍 과제

1.1 문맥 전환

작업은 다음 시간에 작업로 전환하기 위해 작업의 상태를 전환하기 전에 저장됩니다 1. 당신은 그 작업의 상태를로드 할 수 있습니다. 그래서 작업은 다시로드하는 과정에서 컨텍스트 스위치를 저장하는 것입니다.

2. 어떻게 컨텍스트 스위칭을 줄이기 위해?

  • 잠금이없는 동시 프로그래밍

  • CAS 알고리즘

  • 최소 스레드

  • 사용하여 코 루틴 : 멀티 태스크 스케줄링은 단일 스레드로 구현하고, 단일 스레드에 복수의 태스크 사이의 스위칭을 유지

1.2 교착 상태

1. 어떻게 교착 상태를 피하기 위해?

  • 스레드가 더 잠금을 얻을하지 마십시오

  • 더 많은 자원을 차지 다시 스레드 잠금을 피하고, 오직 하나의 스레드가 자원을 차지할 수 있도록 노력

  • 시간 잠금을 사용 lock.tryLock (타임 아웃)를 사용하는 대신 내부 로킹 메커니즘을 사용하여 시도

  • 데이터베이스 잠금의 경우, 데이터베이스 연결을 잠금 및 잠금 해제를해야한다, 그렇지 않으면 상황은 실패 나타납니다

구현 원리를 기초 제 2 장 자바 동시성 메커니즘

2.1 휘발성 응용 프로그램

  1. 휘발성 경량 그는 여러 동시 프로세서의 변수를 공유하기 위해, 동기화 "가시성" . 필드가 volatile로 선언 된 경우, Java 스레드 메모리 모델 보장하지만이 모든 스레드는이 변수의 값이 동일 볼 수있다.

  2. 이 컨텍스트 스위칭 및 스케줄링 발생하지 않습니다.

  3. 두 가지의 원칙의 휘발성 실현

  • 프로세서 캐시 원인 잠금 접두사 지침 메모리에 다시 기록
  • 프로세서의 캐시 메모리가 원인으로 다시 작성 다른 프로세서의 캐시가 잘못되었습니다

2.2 동기화

1.synchronized 기준은 동기화를 달성하기 위하여 자바 각 객체가 로크로서 사용될 수있다.

2. 세 가지 형태 :

  • 통상 동기 방법, 로크는 오브젝트의 현재 인스턴스이고;
  • 정적 동기화 방법, 로크는 현재 클래스의 클래스 오브젝트이고;
  • 동기 부호 블록에 대한 개체 잠금 동기화 브래킷 구성된다.

비교 2.2.2 업그레이드 및 잠금

  1. 없음 잠금 상태 없다 - "편견 잠금 -"경량 잠금 - "헤비급 잠금. 잠금은 다운 그레이드 할 수 없습니다 업그레이드 할 수 있습니다.

  2. 닫기 지연을 고정 바이어스 (보통 바이어스 잠금은 프로그램이 몇 초 시작 후에 만 ​​활성화됩니다)

-XX:BiasedLockingStartupDelay = 0;

  1. 닫기 바이어스 잠금 (경량 잠금 프로그램을 입력 한 후 기본 상태)

-XX:UseBiasedLocking = false;

  1. 경량 잠금 해제 잠금 헤비급 잠금 확장의 뒷면에있는 잠금 경합, 잠금의 현재 존재를 나타내는 실패합니다.

5. 잠금 장점과 단점 :

  • 이점
  1. 바이어스 잠금 : 잠금 및 추가 소비를 해제하지 만이 차이를 나노초과 비교하여 비동기 방법을 수행한다

  2. 경량 잠금 : 스레드가 절차의 응답 속도를 향상, 경쟁을 차단하지 않습니다;

  3. 헤비급 잠금 : 스핀를 사용하지 않고 스레드 경쟁, CPU를 소비하지 않습니다

  • 결점
  1. 잠금을 바이어스 : 스레드 잠금 경합이있는 경우, 소비의 추가 잠금 해지를 가져올 것이다;

  2. 경량 잠금 : 스레드를 경쟁 잠금을 가져올 수 없습니다 아직도 경우, 스핀을 사용하여 CPU를 소모합니다

  3. 헤비급 잠금 : 스레드가 차단되고, 느린 응답 시간

  • 적용 현장
  1. 편향된 로킹 : 하나의 스레드 만이 동기 블록에 액세스하도록 구성되는

  2. 경량 잠금 : 응답 시간의 추구, 매우 빠르게의 구현 동기화 된 블록

  3. 헤비급 잠금 : 특정 동기 블록 긴 실행 속도의 추구

2.3 원자 조작

  1. 어떻게 프로세서 구현 원자 조작?

버스 키 보장 자성을 이용하여 (1);

캐시 잠금 보증 자성을 사용하여 (2);

이가지 경우를 제외하고 :

  • 동작 데이터는 상기 프로세서 또는 프로세서 버스 로크 전화에서 데이터의 캐시 라인의 다수의 동작 내에 캐시 될 수 없을 때
  • 일부 프로세서 캐시 잠금을 지원하지 않습니다
  1. 어떻게 자바 원자 연산을 구현하는 방법?

저자 로킹환상 CAS 구현;

(1) CAS 사이클 동작의 자성을 이용하여

프로세서 구현에 의해 제공 CMPXCHG 명령하여 CAS JVM의 동작. 기본적인 아이디어는 스핀 사이클 CAS CAS 지금까지 성공적인 작동을 알 달성하는 것입니다.

세 원자 (2) CAS 작동

  1. ABA 문제

    1. 해결 방법 : 버전 번호를 사용하여이 버전 번호가 변수 앞에 추가되고 각 변수가 업데이트 될 때 버전 번호 +1
  2. 대형 오버 헤드 긴 사이클 시간

  3. 만 공유 변수를 보장 할 수 원자 조작

(3) 달성하기위한 로크기구를 사용

이 메커니즘은 메모리 영역은 잠금 장치를 작동 할 수 있도록 잠금을 획득 할 수있는 스레드가 아니라 보장합니다.

제 4 장 자바 병행 프로그래밍의 기초

4.1 소개 스레드

4.1.1 스레드 무엇입니까

1. 현대 운영 체제 스케줄링의 최소 단위는 스레드라고도 경량 프로세스입니다 . 여러 스레드가이 스레드가 자신의 카운터, 스택, 스택 특성, 지역 변수를 가지고 프로세스를 생성 할 수 있으며, 공유 메모리 변수에 액세스 할 수 있습니다.

4.1.2를 사용하는 이유 멀티 스레딩

  1. 이상의 프로세서 코어
  2. 빠른 응답 시간
  3. 더 나은 프로그래밍 모델

4.1.3 스레드 우선 순위

  1. 자주 폐색 (수면 또는 I / O 동작)에 대한 스레드를 높은 우선 순위를 설정해야하고, 강조 계산 스레드는 프로세서가 독점되지 않도록 우선 순위를 낮추기 위해 설정된다 (CPU보다 연산 시간 또는 일부가 필요함);

  2. OS가 우선 순위 설정을위한 자바 스레드를 무시할 수 있기 때문에 스레드 우선 순위는 프로그램의 정확성에 같은 종속되지 않습니다.

4.1.4 스레드 상태

4.1.5 데몬 스레드

  1. 주로 백그라운드 프로그램 예약 및 지원 작품으로 사용되는지지 형 스레드, 평균, 데몬 스레드가 자바 가상 머신을 존재하지 않는, Java 가상 머신이 종료됩니다 .

  2. (참) Thread.setDarmon이 필요 스레드를 시작하기 전에 설정해야합니다, 설정할 수 있습니다.

  3. 데몬 스레드를 만들 때, 당신은 마지막으로 정리 또는 종료 논리 자원의 이행을 보장하기 위해 블록의 내용에 의존 할 수 없다.

4.2 시작 및 종료 스레드

4.2.1 건설 스레드

4.2.2 시작 스레드

초기화가 완료되면, 스레드를 시작할 수 있습니다 시작 () 메서드를 호출합니다. 스레드를 시작하기 전에 스레드는 스레드 이름을 설정하는 것이 가장 좋습니다.

4.2.3 중단 이해

  1. 인터럽트 : 다른 스레드에 의해 실행되는 스레드 인터럽트 조작되었는지 여부를 나타내는 플래그 스레드의 속성으로 이해했다. 다른 스레드 인터럽트와 마찬가지로 스레드가 인터럽트 작업 () 메소드를 인터럽트 호출하여 호출 스레드의 다른 스레드를했다.

  2. 중단 여부를 결정하는 스레드 (), 당신은 또한 isInterrupted에 의해 현재의 thread의 인터럽트 플래그 재설정 정적 방법 Thread.interrupted ()를 호출 할 수 있습니다.

4.3 스레드 간 통신

4.3.2 대기 / 알림 메커니즘

통화 대기 (),),) (주가는 notifyAll을 (통지 :

  • 우리는 객체 잠금 전화를 걸 때 사용합니다;
  • ()를 호출 대기 한 후, 대기 중, 현재 스레드 대상물 큐에 넣고, 실행 스레드 상태 변화;
  • 대기에서 스레드로 복귀 할 수있는 기회를 기다린 후 통보하고가는 notifyAll하는, 호출 스레드 출시 잠금 요구를 통지의 notifyAll 호출 후, 아직도 대기 스레드는 대기에서 반환하지 않습니다;
  • 통지의 notifyAll 동기 큐 스레드 상태 변화에 의해 이동이 차단 길 기다리고 큐로 이동 스레드를 대기
  • 전제 대기 메소드가 리턴에서 호출 개체가 잠금을 확보하는 것입니다

4.3.3 대기 고전적인 패러다임 / 통지

파티 기다립니다 :

  1. 객체 잠금을 획득
  2. 조건이 충족되지 않는 경우, 통지 아직 확인 조건 인 후 객체의 대기 () 메소드를 호출
  3. 논리 상태를 대응하는 실행 만족
  4. 의사 코드
synchronized(对象) {
    while(条件不满足) {
        对象.wait();
    }
    // 对应的逻辑处理 
}

파티 통보 :

  1. 객체 잠금을 얻으려면
  2. 변경 조건
  3. 대상 스레드에 대한 모든 대기 통보
  4. 의사 코드
synchronized(对象) {    
    改变条件    
    对象.notifyAll(); 
} 

4.3.4 입력 및 출력 흐름 덕트

4.3.5를 Thread.join () 사용

스레드 A가 () 문을를 Thread.join를 실행하는 경우, 그 의미는 다음과 같습니다 스레드 대기 스레드 후 현재 스레드를 Thread.join ()에서 반환을 종료 할 수 있습니다. 스레드가 스레드를 제공 할뿐만 아니라 가입 () 메소드는 또한 (긴 밀)를 결합하고 (긴 분쇄기, 나노 INT) 두 개의 제한 수단을 포함하는 가입 제공된다.

4.4 스레드 응용 프로그램 예제

4.4.3 스레드 풀과 그 예

스레드 풀 : 이전 스레드, 스레드 창조의 여러 수를 생성하고 사용자가 직접 제어 할 수없는 임무를 완료하려면이 상황에서 스레드의 고정 또는 상대적으로 고정 된 반복 번호를 사용 . 한편으로 이러한 장점, 스레드가 시스템 리소스 오버 헤드의 빈번한 스레드 생성과 소멸을 제거하는 반면에,는 얼굴 과량의 과제는 점진적인 열화를 제출할 수있다 .

5 자바 장 잠금

5.1 잠금 인터페이스

  1. 그리고 차이를 동기화 :
  • 암시 취득 누락 잠금 해제 (또는 동기 블록에 의해 제공되는 방법에 의해) 편의;
  • 잠금 획득을 가지고 조작성의 놓습니다. 인터럽트 잠금 획득 시간 제한 및 동기화 된 키워드 잠금 및 기타 동기화 기능을 얻을 사용할 수 없습니다
Lock lock = new ReentrantLock(); 
lock.lock(); 
try {    
} finally {    
    lock.unlock(); 
} 
  1. 마지막으로 잠금을 해제 한 후 출시 될 궁극적으로 잠금을 얻을 수 있는지 확인하고

  2. 인수가 잠금시 발생하는 것처럼 (사용자 정의 구현 잠금) 이상, 예외가 발생, try 블록을 작성하는 과정에서 고정되지 마십시오, 그것은 또한 아무 이유없이 잠금의 해제로 이어질 것

4. 특징 :

  • 잠금을 얻기위한 시도를 비는 차단 : 현재 스레드를 잠금을 획득하는 잠금이 성공적으로 획득하고 잠금을 또 다른 스레드에 의해 인수되지 않은이 시점 경우;
  • 잠금을 획득 중단 될 수 :
  • 잠금을 취득 제한 시간 :

5.2 큐 동기화

AbstractQueuedSynchronizer의 (AQS) - 동기화

주요 이용 동기가 상속 동기를 통해, 서브 클래스를 상속 및 동기화 상태를 관리 할 수있는 자사의 추상 메소드를 구현되고, 필연적으로 추상 메소드의 구현 과정에서 동기화 상태를 변경해야합니다, 당신은 제공된 사용 동기에 필요 세 가지 방법이 작동합니다. 이렇게 동기화 동기화 구성 요소의 다른 유형의 구현을 용이하게하기 위해, 또한, 동기 상태로의 공유 액세스를 지원할 수있는 동기화 된 상태로 둘 배타적 액세스를 지원한다 (ReentrantLock와, ReentrantReadWriteLock, CountDownLatch를)

5.3 재진입 잠금

로크를 획득하는 경우 로크는 리소스의 나사 체결 복제를 지원할 수 있음을 나타내고, 추가로, 또한 공정과 불공정 선택을 지원한다.

공정한 액세스 잠금 : 그 자물쇠에 긴 대기 스레드 우선 순위 액세스입니다.

5.4 읽기 - 쓰기 잠금

5.5 LockSupport 도구

5.6 조건 인터페이스

제 6 장 자바 동시 용기 및 프레임 워크

원리 및 응용 6.1 ConcurrentHashMap의 구현

스레드 안전하고 효율적인 HashMap의

6.1.1 왜 사용 하시겠습니까?

동시 프로그래밍에서 사용 되는 HashMap 무한 루프가 발생할 수 및 사용 스레드 안전 해시 비효율적 .

  1. 스레드 안전의 HashMap

멀티 스레딩은 풋 동작을 해결하기 위해 100 %의 CPU 사용률의 결과, 무한 루프를 야기 할 것이다. 엔트리리스트 데이터 환형 구조를 형성 HashMap의 리드.

  1. 비효율적 인 해시

보안 스레드를 보장하기 위해 동기화하지만, 스레드 경쟁 인센티브와 비효율적 인 사용;

  1. ConcurrentHashMap의 유효 속도를 향상시킬 수있는 고정 세그먼트에 대한 동시 액세스 기술

먼저, 데이터에 의해 세그먼트에 저장 하고를 자물쇠와 데이터마다 최종 잠금 액세스 데이터 중 하나를, 다른 데이터 세그먼트가 다른 스레드가 액세스 할 수있는 경우, 스레드는 보유하고있다.

6.1.2 ConcurrentHashMap의 구조

세그먼트 데이터 구조는 ConcurrentHashMap의 HashEntry 및 데이터 구조입니다. 세그먼트는 반복적 인 잠금 , 잠금 역할 키 데이터를 기억 HashEntry .

ConcurrentHashMap의 각 HashEntry는 링크드리스트 구조의 소자이며, 세그먼트 A 세그먼트의 배열은 HashEntry 어레이를 포함 포함하는 HashEntry 어레이 요소 지키고 각 세그먼트 어레이 HashEntry의 요소가 변경 될시에는, 먼저 획득해야 자신의 해당 세그먼트 잠금 .

도 클래스 ConcurrentHashMap의
도 구성 ConcurrentHashMap의

6.1.3 ConcurrentHashMap의 초기화

  1. 배열 초기화 세그먼트

  2. 초기화 segmentShift 및 segmentMask

    1. 16까지 segmentShift
    2. 65535까지 segmentMask
  3. 각 세그먼트를 초기화

6.1.4 위치 세그먼트

로크 세그먼트 ConcurrentHashMap의 세그먼트가 그 데이터의 다른 부분을 보호하고, 사용하기 때문에 소자의 삽입이, 제 해시 알고리즘을 통해 세그먼트를 찾을 때한다.

목적 다시 해시 : 요소가 균일하여 액세스 용기의 효율성을 향상, 다른 세그먼트에 배포 할 수 있도록하는 것이, 해시 충돌을 줄일 수 있습니다.

위치 세그먼트

최종 세그먼트 <K, V> segmentFor (INT 해시) {창 세그먼트 [(해시 >>> segmentShift) segmentMask]; }

6.1.5 ConcurrentHashMap의 작업

  1. 작업을 얻을

public V get(Object key) { int hash = hash(key.hashCode()); return segmentFor(hash).get(key,hash); }

整个过程不用加锁,除非读到空值才会加锁重读。

原因: get 方法里将要使用到的共享变量都定义为 volatile 类型,能够在线程之间保持可见性,能够被多线程同时读,并且保证不会读到过期的值,但是只能被单线程写(有一种情况可以被多线程写,就是写入的值不依赖于原值),在get 操作里只需要读不需要写共享变量 count 和 value,所以可以不用加锁。

( hash >>> segmentShift ) & segmentMask // 定位 Segment 使用的 hash 函数 int index = hash & (tab.length - 1) // 定位 HashEntry 使用的 hash 函数

  1. put 操作

要写数据,在操作共享变量时,一定要加锁

两个步骤:

  • 判断是否需要对 Segment 里的 HashEntry 数组进行扩容
  • 定位添加元素的位置,然后将其放在 HashEntry 数组里

(1)是否需要扩容

在插入元素前,先判断 Segment 里的 HashEntry 数组是否超过阈值(threshold),若超过,就对 HashEntry 数组扩容。(HashMap 是在插入后对判断是否已经达到容量,再进行扩容)

(2)如何扩容

创建一个容量为原来2倍的数组,然后将原数组里面的元素进行再散列后插入到新的数组里面。ConcurrentHashMap 只对某个 Segment 进行扩容,更高效。

  1. size 操作

先尝试2次通过不锁住 Segment 的方式来统计各个 Segment 大小,如果统计过程中,容器的 count 发生变化,则采用**加锁的方式(把所有的 Segment 的put、get 和clean方法全部锁住)**来统计所有 Segment 的大小。

6.2 ConcurrentLinkedQueue

实现一个线程安全的队列有两种方式:一种是使用阻塞算法,另一种是非阻塞算法。使用阻塞算法的队列可以用一个锁(入队和出队公用一把锁)或两把锁(出入队用不同锁)的方式来实现。非阻塞的算法可以用循环 CAS 的方式来实现。

ConcurrentLinkedQueue 是一个基于链接节点的无界线程安全队列,采用 FIFO 的规则对节点进行排序。

6.2.2 入队列

  1. 入队列的过程

将入队节点添加到队列的尾部。入队过程两件事儿:①定位出尾结点;②使用 CAS 算法将入队节点设置成尾结点的 next 节点,如不成功则重试。

  1. 定位尾结点

tail 节点并不总是尾结点,所以每次入队都需要通过 tail 节点来找到尾结点

  1. 设置入队节点为尾结点
  2. HOPS 的设计意图

控制并减少 tail 节点的更新频率,而不是每次节点入队后都将 tail 节点更新成尾结点,而是大于等于常量 HOPS 时才更新,提高了入队的效率。

6.2.3 出队列

也是通过设置 HOPS 来确定什么时候更新 head 节点,提高出队效率。

6.3 Java 中的阻塞队列

6.3.1 什么是阻塞队列

BlockingQueue:

  1. 阻塞插入: 队列满时,阻塞插入元素的线程,直至不满;
  2. 阻塞移除: 队列空时,阻塞移除元素的线程,直至不空。
方法/处理方式 抛出异常 返回特殊值 一直阻塞 超时退出
插入方法 add ( e ) offer ( e ) put ( e ) offer ( e, time, unit)
移除方法 remove ( ) poll ( ) take ( ) poll ( time, unit)
检查方法 element ( ) peek ( ) 不可用 不可用

6.3.2 Java 里的阻塞队列

JDK 7:

  1. ArrayBlockingQueue

数组实现的有界阻塞队列。默认不保证线程访问的公平性。为了保证公平性,可能降低吞吐量。

  1. LinkedBlockingQueue

链表实现的有界阻塞队列。默认和最大长度为 Integer.MAX_VALUE

  1. PriorityBlockingQueue

支持优先级的无界阻塞队列。

  1. DelayQueue

支持延时获取元素的无界阻塞队列。使用优先队列实现

  1. SynchronousQueue

不存储元素的阻塞队列,每一个 put 操作必须等待一个 take 操作,否则不能继续添加元素。吞吐量高于 LinkedBlockingQueue 和 ArrayBlockingQueue

  1. LinkedTransferQueue

链表结构的无界阻塞队列

  1. LinkedBlockingDeque

链表结构,双向阻塞。可运用在“工作窃取”模式中。

6.3.3 阻塞队列的实现原理

使用通知模式实现。

6.4 Fork/Join 框架

6.4.1 是什么?

是把一个大任务分割成若干个小任务,最终汇总每个小任务结果后得到大任务结果的框架。

6.4.2 工作窃取算法

是指从某个线程(这个线程自己的活儿干完了,跑去帮别人干活儿)从其他队列里窃取任务来执行。

使用双端队列,被窃取线程从头部拿任务执行,窃取线程从尾部拿任务执行。

优点:

  • 充分利用线程进行并行运算,减少了线程间的竞争。

缺点:

  • 在某些情况下还是存在竞争,比如队列中只有一个任务时。且该算法会消耗更多的系统资源,比如创建多个线程和多个双端队列。

6.4.3 框架设计

使用两个类完成分割任务,执行任务并合并结果。

①ForkJoinTask:创建ForkJoin 任务

两个子类(用时继承):

  1. RecursiveAction: 用于没有返回结果的任务
  2. RecursiveTask: 用于有返回结果的任务

②ForkJoinPool:ForkJoinTask 需要通过 ForkJoinPool 来执行。

Chapter 7 Java 中的13个原子操作类

7.1 原子更新基本类型类

  • AtomicBoolean
  • AtomicInteger
  • AtomicLong

7.2 原子更新数组

  • AtomicIntegerArray
  • AtomicLongArray
  • AtomicReferenceArray
  • AtomicIntegerArray

7.3 原子更新引用类型

  • AtomicReference
  • AtomicReferenceFiledUpdater
  • AtomicMarkableReference

7.4 原子更新字段类

  • AtomicIntegerFiledUpdater
  • AtomicLongFiledUpdater
  • AtomicStampedReference

Chapter 8 Java 中的并发工具类

CountDownLatch、CyclicBarrier和Semphore 并发流程控制;

Exchanger 线程间交换数据

8.1 等待多线程完成的 CountDownLatch

允许一个线程或多个线程等待其他线程完成操作。

CountDownLatch 的构造函数接收一个 int 类型的参数作为计数器,如果你想等待 N 个点完成,这里就传入 N。调用 countDown 方法,N 就减1。CountDownLatch 的 await 方法会阻塞当前线程,直到 N = 0。N 个点,可以是 N 个线程,也可以是1个线程里面的 N 个执行步骤。用在多线程里面,只需要吧 CountDownLatch 的引用传递到线程里即可。

CountDownLatch 不能重新初始化或修改 CountDownLatch 对象的内部计数器的值。

8.2 同步屏障 CyclicBarrier

一组线程到达一个屏障(也可以叫同步点)时被阻塞,直到最后一个线程到达屏障时,屏障才会开门,所有被拦截的线程才会继续运行(继续执行的线程没有先后顺序,取决于CPU调度)。

8.2.1 简介

默认构造方法是 CyclicBarrier (int parties),其参数表示屏障拦截的线程数量,每个线程调用 await 方法告诉 CyclicBarrier 我已经到达屏障,然后当前线程被阻塞。

还有一个高级构造方法 CyclicBarrier (int parties, Runnable barrierAction),用于在线程到达屏障时,优先执行 barrierAction,方便处理更复杂的业务场景。

8.2.3 CyclicBarrier 与 CountDownLatch 的区别

CountDownLatch 的计数器只能使用一次,但是 CyclicBarrier 的计数器可以使用 reset()方法重置,因此 CyclicBarrier 能处理更为复杂的业务场景。

8.3 控制并发线程数的 Semaphore

用来控制同时访问特定资源的线程数量,通过协调各个线程,以保证合理使用公共资源。

  1. 应用场景

做流量控制,特别是公共资源有限的应用场景,比如数据库连接。

8.4 线程间交换数据的 Exchanger

用于线程间的数据交换。它提供一个同步点,在这个同步点,两个线程可以通过 exchange 方法交换彼此的数据。

可以应用于遗传算法

可以应用于校对工作

Chapter 9 Java中的线程池

好处:

  1. 降低资源消耗。
  2. 提高响应速度。
  3. 提高线程的可管理性。

9.1 线程池的实现原理

处理流程中,先判断核心线程池是否已满,满了再判断工作队列是否已满,满了再判断线程池是否已满,满了再执行拒绝策略。

주요 처리 흐름 스레드 풀

ThreadPoolExecutor 执行 execute()方法:

ThreadPoolExecutor입니다 개략적으로 실행

四种情况分析:

  1. 若当前运行的线程少于 coorPoolSize,则创建新线程来执行任务(需要获得全局锁,开销大)
  2. 若运行的线程大于等于 coorPoolSize,则将任务加入 BlockingQueue(大多数时候处于这里)
  3. 若 BlockingQueue 队列已满,则创建新的线程来处理任务(需要获得全局锁,开销大)
  4. 若创建新线程将使当前运行的总线程数超出 maximumPoolSize,那么执行拒绝策略。

工作线程: 线程池创建线程时,会将线程封装成工作线程 Worker,Worker在执行完任务之后还会循环获取工作队列里的任务来执行。

9.2 线程池的使用

9.2.1 线程池创建

通过 ThreadPoolExecutor 创建,很多个参数。

new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, millseconds, runnableTaskQueue, handler)

9.2.2 向线程池提交任务

execute() // 提交不需要返回值的任务,无法判断任务是否被线程池执行成功 submit() // 提交需要返回值的任务

submit(): 线程池会返回一个 future 类型的对象,通过这个对象可以判断任务是否执行成功,且可以通过 future 的 get 方法获取返回值,get 方法会阻塞当前线程直到任务完成,使用 get(long timeout, TimeUnit unit) 会阻塞一段时间后立即返回,这时任务可能还没有执行完成。

9.2.3 关闭线程池

종료 () 또는 shutdownNow의 () 메소드.

원리는 스레드 풀의 모든 작업자 스레드를 통과하는 것입니다, 나는이 작업을 멈추지 않을 수 있습니다 인터럽트 응답 할 수 있도록 다음 하나의 방법 인터럽트 하나 개의 호출에 의해, 스레드를 중단 할 수 있습니다.

일반적으로 스레드 풀을 종료 종료를 사용합니다.

당신은 질문이있는 경우에, 저를 수정하시기 바랍니다!

게시 16 개 원래 기사 · 원 찬양 2 · 조회수 1,278

추천

출처blog.csdn.net/yx185/article/details/103281607