자바 다 중 스 레 드 의 Executor,ExecutorService,Executors,Callable,Future 와 Future Task
21885 단어 안 드 로 이 드 노트
1.도입부
자바 다 중 스 레 드 를 처음 배 울 때
Thread
과 Runnable
을 사용 하여 스 레 드 를 만 들 고 시작 합 니 다.다음 예:Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
});
t1.start();
우 리 는 스스로 Thread 대상 을 만 들 고 시작 해 야 합 니 다.
중요 개념:
Runnable
을 실현 하 는 종 류 는 하나의 스 레 드 가 아니 라 하나의 임무 로 여 겨 져 야 한다.자바 다 중 스 레 드 에서 우 리 는 반드시 명확 한 이 해 를 가 져 야 한다.임무 와 스 레 드 는 서로 다른 개념 이다.스 레 드(Thread)를 사용 하여 작업 을 수행 할 수 있 지만 작업 은 스 레 드 가 아 닙 니 다.2.Executor 실행 스 레 드 사용
일부 기 존 실행 기 는 Thread 대상 을 관리 하 는 데 도움 을 줄 수 있 습 니 다.Thread 대상 을 만 들 고 제어 할 필요 가 없습니다.예 를 들 어 코드 에
new Thread
이나 thread1.start()
을 작성 하지 않 아 도 다 중 스 레 드 를 사용 할 수 있 습 니 다.다음 예:ExecutorService exec = Executors.newCachedThreadPool();
for (int i = 0; i < 5; i++) {//5
exec.submit(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+" doing task");
}
});
}
exec.shutdown(); //
출력 은 다음 과 같 습 니 다:
pool-1-thread-2 doing task
pool-1-thread-1 doing task
pool-1-thread-3 doing task
pool-1-thread-4 doing task
pool-1-thread-5 doing task
출력 을 통 해 알 수 있 듯 이 exec 는 스 레 드 탱크 1 의 5 개의 스 레 드 를 사용 하여 이 몇 가지 임 무 를 수행 했다.
이 예 에서 exec 라 는 Executor 는 관리 임 무 를 맡 고 있 습 니 다.이른바 임 무 는 여기 서 Runnable 인터페이스의 익명 내부 류 를 실현 하 는 것 입 니 다.몇 개의 스 레 드 를 사용 해 야 하 는 지,언제 이 스 레 드 를 시작 해 야 하 는 지,아니면 하나의 스 레 드 로 이 임 무 를 완성 해 야 하 는 지,우 리 는 걱정 할 필요 가 없다.완전히 exec 라 는 실행 기 가 책임 집 니 다.여기 서 exec(new CachedThreadPool)는 수요 에 따라 새 스 레 드 를 만 들 수 있 는 스 레 드 풀 을 가리 키 고 있 습 니 다.
Executors 는 집행 기 에 해당 하 는 공장 류 로 각종 상용 집행 기 를 포함 하 는 공장 방법 으로 상용 집행 기 를 직접 만 들 수 있다.몇 가지 자주 사용 하 는 실행 기 는 다음 과 같다.
Executors.newCachedThreadPool
,필요 에 따라 새로운 스 레 드 풀 을 만 들 수 있 습 니 다.스 레 드 탱크 에서 만 든 스 레 드 는 어떤 작업 을 완성 한 후에 다른 작업 을 수행 하 는 데 사 용 될 수 있 습 니 다.Executors.newFixedThreadPool(int nThreads)
,고정 스 레 드 수 를 다시 사용 할 수 있 는 스 레 드 풀 을 만 듭 니 다.이 스 레 드 탱크 에는 최대 nThread 스 레 드 가 포함 되 어 있 습 니 다.Executors.newSingleThreadExecutor()
,하나의 워 커 스 레 드 를 사용 하 는 Executor 를 만 듭 니 다.임무 가 아무리 많아 도 한 라인 으로 만 임 무 를 완성 할 수 있다.Executors.newSingleThreadScheduledExecutor()
,단일 스 레 드 실행 프로그램 을 만 듭 니 다.주어진 지연 후 명령 을 실행 하거나 정기 적 으로 실행 할 수 있 습 니 다.newSingleThreadExecutor 예 는 다음 과 같 습 니 다.
ExecutorService exec = Executors.newSingleThreadExecutor();
for (int i = 0; i < 5; i++) {
exec.execute(new Runnable() {//execute Runnable ,
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
});
}
exec.shutdown();
출력 은 다음 과 같 습 니 다:
pool-1-thread-1
pool-1-thread-1
pool-1-thread-1
pool-1-thread-1
pool-1-thread-1
5 개의 미 션(new Runnable 5 개)이 있 지만 1 개의 스 레 드 로 만 수행 할 수 있 음 을 알 수 있다.
최고의 실천:우 리 는 기 존의 Executor 또는 Executor Service 실현 류 를 사용 해 야 합 니 다.예 를 들 어 앞에서 말 한 new Cached ThreadPool 은 스 레 드 풀 을 사용 하여 비용 을 낮 출 수 있 습 니 다(새로운 스 레 드 를 만 드 는 데 일정한 대가 가 있 습 니 다).그리고 new Fixed ThreadPool 은 병행 스 레 드 수 를 제한 할 수 있 습 니 다.즉,우 리 는 일반적으로 Executors 의 공장 방법 을 사용 하여 우리 가 필요 로 하 는 실행 기 를 만 드 는 것 이다.
Executor 와 ExecutorService 의 일반적인 방법
execute 방법:
Executor 인 터 페 이 스 는
void execute(Runnable command)
방법 밖 에 없다.방법 성명 에서 우 리 는 Runnable 형식의 대상 으로 들 어 가 는 것 을 볼 수 있다.자주 사용 하 는 예 는 다음 과 같다.Executor executor = anExecutor;
executor.execute(new RunnableTask1());
그러나 안에서 구체 적 으로 어떻게 실행 하 는 지,스 레 드 실행 여 부 는 해당 하 는 Executor 인터페이스 에서 클래스 를 결정 합 니 다.예 를 들 어 앞의
newCachedThreadPool
은 스 레 드 탱크 를 사용 하여 집행 한다.Executor 는 모든 작업 을 어떻게 실행 하 는 지(스 레 드,스케줄 링 을 어떻게 사용 하 는 지)와 분리 합 니 다.submit 방법:
ExecutorService
인 터 페 이 스 는 Executor 인 터 페 이 스 를 계승 하여 부모 인터페이스 의 execute 방법 을 확장 했다.자주 쓰 는 submit 방법 이 두 가지 가 있어 요.Future> submit(Runnable task)
Future submit(Callable task)
이 두 가지 일반적인 방법 중 하 나 는 Runnable 형식 입 참 을 받 고 하 나 는 Callable 형식 입 참 을 받 는 것 을 볼 수 있 습 니 다.Callable 입 참 은 작업 반환 값 을 허용 하고 Runnable 은 반환 값 이 없습니다.즉,스 레 드 가 되 돌아 오 기 를 원한 다 면 Callable 형식 으로 참여 해 야 한 다 는 것 이다.
invokeAll 과 invokeAny 방법:
Callable 작업 을 일괄 실행 합 니 다.이 중 invokeAll 은 모든 작업 이 완료 되면 결 과 를 나타 내 는 Future 목록 입 니 다.invokeany 는 이 작업 의 모든 임 무 를 완성 한 후에 돌아 갑 니 다.두 가지 방법의 반환 결 과 를 통 해 우 리 는 두 가지 방법의 차 이 를 알 수 있다.
List> invokeAll(Collection extends Callable> tasks)
T invokeAny(Collection extends Callable> tasks)
invoke All 은 List 로 돌 아 왔 고 invoke 는
T
으로 돌 아 왔 다.shutdown()방법:
순서대로 닫 기 를 시작 하고 이전에 제출 한 작업 을 수행 하지만 새 작업 은 받 지 않 습 니 다.이 방법 을 실행 하면 스 레 드 탱크 는 작업 이 끝 난 후에 닫 히 고 새로운 작업 을 받 지 않 습 니 다.
shutdown()
방법 을 실행 한 후 execute
방법 을 실행 하면 Rejected Execution Exception 을 직접 던 집 니 다.왜 알 았 냐 고 묻 지 마.원칙:ExecutorService(라인 풀)가 더 이상 사용 하지 않 는 다 면 자원 을 회수 하기 위해 닫 아야 합 니 다.이것 은 더 이상 사용 하지 않도록 주의해 야 한다.
상술 한 방법 이 비교적 많 으 니 뒤의 실례 에 맞추어 이해 할 수 있다.execute 방법 과 shutdown 방법 을 먼저 기억 할 수 있 습 니 다.
3.Callable 과 Future 사용
호출 가능 인터페이스
Runnable
인터페이스 에 있 는 public void run()
방법 은 반환 값 이 없습니다.만약 에 우리 가 스 레 드 연산 후 결 과 를 되 돌려 주 기 를 원한 다 면 Runnable 을 사용 하면 어 쩔 수 없습니다.이때 우 리 는 Callable
을 사용 해 야 한다.Callable 은 반환 값 이 있 는 작업 을 대표 합 니 다.Callable 인 터 페 이 스 를 실현 하 는 클래스 는 다음 과 같 습 니 다.class CalcTask implements Callable<String> {
@Override
public String call() throws Exception {
return Thread.currentThread().getName();
}
}
이 작업 은 비교적 간단 합 니 다.바로 현재 스 레 드 의 이름 을 되 돌려 주 는 것 입 니 다.Runnable 에 비해 반환 값 이 있 습 니 다.여기 서 반환 값 유형 은 String 이 고 다른 유형 일 수도 있 습 니 다.
다음 코드 를 사용 하여 호출 합 니 다:
ExecutorService exec = Executors.newCachedThreadPool();
List> taskList = new ArrayList>();
/* 5 */
for (int i = 0; i < 5; i++) {
taskList.add(new CalcTask());
}
/* : */
List> resultList = new ArrayList>();
try {
/*invokeAll , submit */
resultList = exec.invokeAll(taskList);
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
/* future */
for (Future future : resultList) {
System.out.println(future.get());//get
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
출력 은 다음 과 같 습 니 다:
pool-1-thread-1
pool-1-thread-2
pool-1-thread-3
pool-1-thread-4
pool-1-thread-5
Future 인터페이스
위의 예 에서 우 리 는 Future 인 터 페 이 스 를 사용 했다.Future 는 비동기 계산 결 과 를 나타 낸다.그것 은 계산 이 완 료 될 때 까지 계산 하 는 방법 을 검사 하고 계산 결 과 를 얻 는 방법 을 제공 했다.위의 예 에서 exec 실행 기 는 Callable 형식의 작업 목록 을 실행 하고 Futuer 형식의 결과 목록 resultList 를 얻 었 습 니 다.
get 방법
계산 이 끝 날 때 까지 기 다 렸 다가 결 과 를 얻 습 니 다.
isDone 방법
작업 이 끝 났 는 지 확인 하 는 데 사용 합 니 다.예 는 다음 과 같 습 니 다.
/* Callable */
Callable callableTask = new Callable() {
@Override
public Integer call() throws Exception {
System.out.println("Calculating 1+1!");
TimeUnit.SECONDS.sleep(2);// 2
return 2;
}
};
ExecutorService executor = Executors.newCachedThreadPool();
Future result = executor.submit(callableTask);
executor.shutdown();
while(!result.isDone()){//isDone()
System.out.println(" ");
TimeUnit.SECONDS.sleep(1);// 1
}
try {
System.out.println(" :"+result.get());
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
출력 은 다음 과 같 습 니 다:
Calculating 1+1!
:2
4.FutureTask
FutureTask
종 류 는 Future 인터페이스의 실현 이다.Future Task 류 는 Runnable Future 인 터 페 이 스 를 실 현 했 고 Runnable Future 는 Runnable 인터페이스 와 Future 인 터 페 이 스 를 계 승 했 기 때문에:FutureTask futureTask = new FutureTask<>(new Callable() {
@Override
public Integer call() throws Exception {
System.out.println("futureTask is wokring 1+1!");
return 2;
}
});
Thread t1 = new Thread(futureTask);//1. Runnable
t1.start();
try {
System.out.println(futureTask.get());//2. Future
} catch (ExecutionException e) {
e.printStackTrace();
}
출력 은 다음 과 같 습 니 다:
futureTask is wokring 1+1!
2
에서 알 수 있 듯 이 Future Task 는 반환 값 이 있 는 Runnable 작업 으로 사용 할 수 있 습 니 다.분석:
FutureTask futureTask = new FutureTask<>(new Callable...)
은 Callable 작업 을 Runnable 작업 으로 전환 하면 스 레 드 를 사용 하여 이 작업 을 수행 할 수 있 습 니 다.반면 futureTask.get()
은 Callable 을 Future 로 전환 해 비동기 연산 의 결 과 를 얻 는 셈 이다.ExecutorService 실행 기 는 Runnable 과 Callable 형식의 입 참 을 받 는 것 외 에 Future Task 형식 도 받 을 수 있 습 니 다.예 는 다음 과 같 습 니 다.
FutureTask futureTask = new FutureTask<>(new Callable() {
@Override
public Integer call() throws Exception {
System.out.println("futureTask is wokring 1+1!");
TimeUnit.SECONDS.sleep(2);
return 2;
}
});
ExecutorService executor = Executors.newCachedThreadPool();
executor.submit(futureTask);// execute, Runnable
executor.shutdown();
while(!futureTask.isDone()){
System.out.println(" , ");
TimeUnit.SECONDS.sleep(1);
}
try {
System.out.println(" :"+futureTask.get());
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
학습 노트: Android 의 MVC 모드 와 MVP 모드업무 논리, 데이터, 인터페이스 로 분 리 된 방법 으로 코드 를 구성 하고 업무 논 리 를 한 위 젯 에 모 으 며 개성 화 된 맞 춤 형 인터페이스 와 사용자 의 상호작용 을 개선 하 는 동시에 업무 논 리 를 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.