Java 스레드 풀 상세 정보
1. Executors 공장 클래스는 스레드 탱크를 만드는 데 사용되며, 이 공장 클래스는 다음과 같은 몇 가지 정적 공장 방법으로 대응하는 스레드 탱크를 만드는 것을 포함한다.생성된 스레드 탱크는 Executor Service 대상입니다. 이 대상의submit 방법이나 execute 방법으로 해당하는 Runnable 또는 Callable 작업을 수행합니다.스레드 탱크 자체가 더 이상 필요하지 않을 때shutdown () 방법을 호출하여 스레드 탱크를 정지합니다. 이 방법을 호출하면 이 스레드 탱크는 작업을 추가하는 것을 허용하지 않지만, 추가된 모든 작업이 완료될 때까지 사망합니다.
1. newCachedThreadPool(), 캐시 기능이 있는 스레드 풀을 만들고 이 스레드 풀에 제출된 작업(Runnable 또는 Callable 대상)이 만든 스레드를 실행합니다. 실행이 완료되면 뒤에 수행해야 할 작업에 캐시됩니다.
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class CacheThreadPool {
static class Task implements Runnable {
@Override
public void run() {
System.out.println(this + " " + Thread.currentThread().getName() + " AllStackTraces map size: "
+ Thread.currentThread().getAllStackTraces().size());
}
}
public static void main(String[] args) {
ExecutorService cacheThreadPool = Executors.newCachedThreadPool();
//
for(int i = 0 ; i < 3; i++) {
cacheThreadPool.execute(new Task());
}
// ,
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
for(int i = 0 ; i < 3; i++) {
cacheThreadPool.execute(new Task());
}
}
}
실행 결과는 다음과 같습니다.
CacheThreadPool$Task@2d312eb9 pool-1-thread-1 AllStackTraces map size: 7
CacheThreadPool$Task@59522b86 pool-1-thread-3 AllStackTraces map size: 7
CacheThreadPool$Task@73dbb89f pool-1-thread-2 AllStackTraces map size: 7
CacheThreadPool$Task@5795cedc pool-1-thread-3 AllStackTraces map size: 7
CacheThreadPool$Task@256d5600 pool-1-thread-1 AllStackTraces map size: 7
CacheThreadPool$Task@7d1c5894 pool-1-thread-2 AllStackTraces map size: 7
스레드 탱크의 스레드 대상이 캐시되어 새 작업이 실행될 때 다시 사용됩니다.그러나 특히 많은 병발이 있을 때, 캐시 스레드 탱크는 많은 스레드 대상을 만들 것이다.2. newFixedThreadPool(int nThreads)은 지정된 스레드 개수를 만들고 스레드를 다시 사용할 수 있는 스레드 탱크를 만듭니다.
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class FixedThreadPool {
static class Task implements Runnable {
@Override
public void run() {
System.out.println(this + " " + Thread.currentThread().getName() + " AllStackTraces map size: "
+ Thread.currentThread().getAllStackTraces().size());
}
}
public static void main(String[] args) {
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);
//
for (int i = 0; i < 5; i++) {
fixedThreadPool.execute(new Task());
}
// ,
try {
Thread.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
for (int i = 0; i < 3; i++) {
fixedThreadPool.execute(new Task());
}
}
}
실행 결과:
FixedThreadPool$Task@7045c12d pool-1-thread-2 AllStackTraces map size: 7
FixedThreadPool$Task@50fa0bef pool-1-thread-2 AllStackTraces map size: 7
FixedThreadPool$Task@ccb1870 pool-1-thread-2 AllStackTraces map size: 7
FixedThreadPool$Task@7392b4e3 pool-1-thread-1 AllStackTraces map size: 7
FixedThreadPool$Task@5bdeff18 pool-1-thread-2 AllStackTraces map size: 7
FixedThreadPool$Task@7d5554e1 pool-1-thread-1 AllStackTraces map size: 7
FixedThreadPool$Task@24468092 pool-1-thread-3 AllStackTraces map size: 7
FixedThreadPool$Task@fa7b978 pool-1-thread-2 AllStackTraces map size: 7
3. newSingleThreadExecutor(), newFixedThreadPool을 호출하는 것과 같은 단일 스레드 풀을 만듭니다.4. newSheduledThreadPool(intcorePoolSize), 지정한 스레드 수의 스레드 탱크를 만듭니다. 지정한 딜레이 후에 스레드를 실행할 수 있습니다.어떤 주기로 어떤 라인을 반복해서 실행할 수도 있습니다. shutdown () 을 호출하여 스레드 탱크를 닫는 것을 알고 있습니다.
예는 다음과 같습니다.
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class ScheduledThreadPool {
static class Task implements Runnable {
@Override
public void run() {
System.out.println("time " + System.currentTimeMillis() + " " + Thread.currentThread().getName() + " AllStackTraces map size: "
+ Thread.currentThread().getAllStackTraces().size());
}
}
public static void main(String[] args) {
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(3);
scheduledExecutorService.schedule(new Task(), 3, TimeUnit.SECONDS);
scheduledExecutorService.scheduleAtFixedRate(new Task(), 3, 5, TimeUnit.SECONDS);
try {
Thread.sleep(30 * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
scheduledExecutorService.shutdown();
}
}
실행 결과는 다음과 같습니다.
time 1458921795240 pool-1-thread-1 AllStackTraces map size: 6
time 1458921795241 pool-1-thread-2 AllStackTraces map size: 6
time 1458921800240 pool-1-thread-1 AllStackTraces map size: 7
time 1458921805240 pool-1-thread-1 AllStackTraces map size: 7
time 1458921810240 pool-1-thread-1 AllStackTraces map size: 7
time 1458921815240 pool-1-thread-1 AllStackTraces map size: 7
time 1458921820240 pool-1-thread-1 AllStackTraces map size: 7
운행 시간에서 알 수 있듯이 임무는 5초의 주기에 따라 집행된다.5. newSingleThreadScheduledExecutor()는 하나의 라인만 있는 라인 풀을 만들고 newScheduledThreadPool(1)을 함께 사용합니다.
2. ForkJoinPool 및 ForkJoinTask
ForkJoinPool은 Executor Service의 실현 클래스로 하나의 임무를 여러 개의 작은 임무로 나누어 병렬적으로 계산하고 여러 개의 작은 임무의 계산 결과를 전체적인 계산 결과로 통합하는 것을 지원합니다.그것은 두 개의 구조 함수가 있다
ForkJoinPool(int parallelism) 병렬 라인을 포함하는 ForkJoinPool을 만듭니다.
ForkJoinPool(), Runtime.availableProcessors() 메서드는 parallelism 매개 변수로 값을 되돌려 ForkJoinPool을 생성합니다.
ForkJoinTask는 병렬적이고 통합된 작업을 나타냅니다.이것은 Future
Recurive Action의 예는 0-300의 숫자를 병렬 출력하는 것입니다.
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveAction;
import java.util.concurrent.TimeUnit;
public class ActionForkJoinTask {
static class PrintTask extends RecursiveAction {
private static final int THRESHOLD = 50;
private int start;
private int end;
public PrintTask(int start, int end) {
this.start = start;
this.end = end;
}
@Override
protected void compute() {
if (end - start < THRESHOLD) {
for(int i = start; i < end; i++) {
System.out.println(Thread.currentThread().getName() + " " + i);
}
} else {
int middle = (start + end) / 2;
PrintTask left = new PrintTask(start, middle);
PrintTask right = new PrintTask(middle, end);
left.fork();
right.fork();
}
}
}
public static void main(String[] args) {
ForkJoinPool pool = new ForkJoinPool();
pool.submit(new PrintTask(0, 300));
try {
pool.awaitTermination(2, TimeUnit.SECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}
pool.shutdown();
}
}
작은 작업을 분할한 후 작업의 fork() 방법을 호출하여 ForkJoinPool에 추가하여 병행합니다.RecursiveTask 예제: 100개의 정수 구합을 병렬 계산합니다.20개의 수구화로 나누어 결과를 얻고 마지막에 마지막 결과로 합친다.
import java.util.Random;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.Future;
import java.util.concurrent.RecursiveTask;
public class TaskForkJoinTask {
static class CalTask extends RecursiveTask<Integer> {
private static final int THRESHOLD = 20;
private int arr[];
private int start;
private int end;
public CalTask(int[] arr, int start, int end) {
this.arr = arr;
this.start = start;
this.end = end;
}
@Override
protected Integer compute() {
int sum = 0;
if (end - start < THRESHOLD) {
for (int i = start; i < end; i++) {
sum += arr[i];
}
System.out.println(Thread.currentThread().getName() + " sum:" + sum);
return sum;
} else {
int middle = (start + end) / 2;
CalTask left = new CalTask(arr, start, middle);
CalTask right = new CalTask(arr, middle, end);
left.fork();
right.fork();
return left.join() + right.join();
}
}
}
public static void main(String[] args) {
int arr[] = new int[100];
Random random = new Random();
int total = 0;
for (int i = 0; i < arr.length; i++) {
int tmp = random.nextInt(20);
total += (arr[i] = tmp);
}
System.out.println("total " + total);
ForkJoinPool pool = new ForkJoinPool(4);
Future<Integer> future = pool.submit(new CalTask(arr, 0, arr.length));
try {
System.out.println("cal result: " + future.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
pool.shutdown();
}
}
실행 결과는 다음과 같습니다.
total 912
ForkJoinPool-1-worker-2 sum:82
ForkJoinPool-1-worker-2 sum:123
ForkJoinPool-1-worker-2 sum:144
ForkJoinPool-1-worker-3 sum:119
ForkJoinPool-1-worker-2 sum:106
ForkJoinPool-1-worker-2 sum:128
ForkJoinPool-1-worker-2 sum:121
ForkJoinPool-1-worker-3 sum:89
cal result: 912
하위 작업이 끝난 후, 작업의join () 방법을 호출하여 하위 작업 실행 결과를 얻고 마지막 결과를 얻습니다.이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
JPA + QueryDSL 계층형 댓글, 대댓글 구현(2)이번엔 전편에 이어서 계층형 댓글, 대댓글을 다시 리팩토링해볼 예정이다. 이전 게시글에서는 계층형 댓글, 대댓글을 구현은 되었지만 N+1 문제가 있었다. 이번에는 그 N+1 문제를 해결해 볼 것이다. 위의 로직은 이...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.