자바 스 레 드 탱크 원리 깊이 분석

10697 단어 Java스 레 드 탱크
자바 스 레 드 탱크 원리
Executor 프레임 워 크 의 2 단계 스케줄 링 모델
HotSpot VM 모델 에서 자바 스 레 드 는 로 컬 운영 체제 스 레 드 로 일대일 매 핑 됩 니 다.JAVA 스 레 드 가 시 작 될 때 로 컬 운영 체제 스 레 드 를 만 듭 니 다.JAVA 스 레 드 가 종 료 될 때 해당 하 는 운영 체제 스 레 드 도 폐기 되 고 회수 되 며 운영 체 제 는 모든 스 레 드 를 예약 하여 사용 가능 한 CPU 에 배정 합 니 다.
상층 부 에 서 는 JAVA 프로그램 이 여러 작업 으로 분 해 된 다음 응용 급 스케줄 러(Executor)를 사용 하여 이 작업 을 고정된 수량의 스 레 드 로 표시 합 니 다.바 텀 에서 운영 체제 커 널 은 이 스 레 드 를 하드웨어 프로세서 에 투사 한다.
Executor 프레임 워 크 클래스
图片描述
앞서 소 개 된 JAVA 스 레 드 는 작업 단원 이자 실행 메커니즘 이다.Executor 프레임 워 크 에서 우 리 는 작업 단원 과 집행 메커니즘 을 분리 한다.Runnable 과 Callable 은 작업 단원(즉 속칭 임무)이 고 실행 메커니즘 은 Executor 가 제공한다.이렇게 되면 Executor 는 생산자 소비자 모델 을 바탕 으로 임 무 를 제출 하 는 조작 은 생 성자 에 해당 하고 임 무 를 수행 하 는 라인 은 소비자 에 해당 한다.
1.아 날로 그 에서 볼 때 Executor 인 터 페 이 스 는 비동기 작업 수행 프레임 워 크 의 기초 이 고 이 프레임 워 크 는 다양한 유형의 작업 수행 전략 을 지원 할 수 있 습 니 다.

public interface Executor {

  void execute(Runnable command);
}
Executor 인 터 페 이 스 는 실행 방법 을 제공 합 니 다.작업 은 Runnbale 형식 이 고 Callable 형식 은 지원 되 지 않 습 니 다.
2.ExecutorService 인 터 페 이 스 는 Executor 인 터 페 이 스 를 실현 하고 주로 스 레 드 풀 과 submit 를 닫 는 방법 을 제공 합 니 다.

public interface ExecutorService extends Executor {

  List<Runnable> shutdownNow();


  boolean isTerminated();


  <T> Future<T> submit(Callable<T> task);

 }
또한 이 인 터 페 이 스 는 두 가지 중요 한 실현 유형 이 있 는데 그것 이 바로 Thread PoolExecutor 와 Scheduled Thread PoolExecutor 이다.
그 중에서 Thread PoolExecutor 는 스 레 드 탱크 의 핵심 실현 클래스 로 제출 된 작업 을 수행 합 니 다.한편,Scheduled Thread PoolExecutor 는 실행 클래스 로 주어진 지연 후에 작업 을 실행 하거나 정기 적 으로 명령 을 수행 할 수 있 습 니 다.
이전 글 에서 저 는 Thread PoolExecutor 를 사용 하여 서로 다른 파 라 메 터 를 지정 하여 필요 한 스 레 드 풀 을 만 들 었 습 니 다.그러나 뒤의 작업 에서 이런 방식 을 권장 하지 않 습 니 다.Exectuors 공장 방법 으로 스 레 드 풀 을 만 드 는 것 을 추천 합 니 다.
먼저 스 레 드 탱크 와 스 레 드 그룹(ThreadGroup 과 ThreadPoolExecutor)이라는 두 개념 을 구별 합 니 다.
a.스 레 드 그룹 은 하나의 스 레 드 의 집합 을 나타 낸다.
b.스 레 드 탱크 는 스 레 드 의 생명 주기 비용 문제 와 자원 부족 문제 에 해결 방안 을 제공 하 는 것 으로 주로 스 레 드 를 관리 하 는 데 사용 된다.
Executors 는 3 가지 유형의 ThreadPoolExecutor:SingleThreadExecutor,Fixed ThreadExecutor,CachedThreadPool 을 만 들 수 있 습 니 다.
a,SingleThreadExecutor:단일 라인 스 레 드 탱크

ExecutorService threadPool = Executors.newSingleThreadExecutor();

public static ExecutorService newSingleThreadExecutor() {
    return new FinalizableDelegatedExecutorService
      (new ThreadPoolExecutor(1, 1,
                  0L, TimeUnit.MILLISECONDS,
                  new LinkedBlockingQueue<Runnable>()));
  }
원본 코드 를 보면 알 수 있 듯 이 단선 스 레 드 탱크 의 생 성 도 Thread PoolExecutor 를 통 해 이 루어 집 니 다.그 안의 핵심 스 레 드 수 와 스 레 드 수 는 모두 1 이 고 작업 대기 열 은 무한 대기 열 을 사용 합 니 다.단일 스 레 드 작업 이기 때문에 매번 하나의 작업 만 처리 할 수 있 기 때문에 뒤의 모든 작업 은 작업 대기 열 에 막 혀 하나의 작업 만 수행 할 수 있 습 니 다.
b.FixedThreadExecutor:고정 크기 스 레 드 탱크

ExecutorService threadPool = Executors.newFixedThreadPool(5);

public static ExecutorService newFixedThreadPool(int nThreads) {
    return new ThreadPoolExecutor(nThreads, nThreads,
                   0L, TimeUnit.MILLISECONDS,
                   new LinkedBlockingQueue<Runnable>());
  }
이것 은 단일 스 레 드 와 유사 합 니 다.고정 크기 의 스 레 드 수 를 만 들 었 을 뿐 입 니 다.
c,CachedThreadPool:무한 스 레 드 탱크

ExecutorService threadPool = Executors.newCachedThreadPool();

public static ExecutorService newCachedThreadPool() {
    return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                   60L, TimeUnit.SECONDS,
                   new SynchronousQueue<Runnable>());
  }
무 계 스 레 드 탱크 는 작업 대기 열 이 없 으 면 작업 이 들 어 오 면 실행 되 고 스 레 드 수량 이 부족 하면 만 드 는 것 을 의미 합 니 다.앞의 두 가지 차이 점 은 남 은 스 레 드 는 회수 되 고 남 은 시간 은 60s 입 니 다.이것 은 단기 비동기 프로그램 을 많이 실행 하거나 부하 가 가 벼 운 서버 에 적용 된다.
Callable,Future,FutureTash 상세 설명
Callable 과 Future 는 JAVA 의 후속 버 전에 서 도입 되 었 습 니 다.Callable 은 Runnable 인터페이스 와 유사 하고 Callable 인 터 페 이 스 를 실현 하 는 클래스 와 Runnable 을 실현 하 는 클래스 는 모두 스 레 드 로 실 행 될 수 있 는 작업 입 니 다.
삼자 간 의 관계:
Callable 은 Runnable 에 포 장 된 비동기 연산 작업 입 니 다.
Future 는 Callable 비동기 연산 결 과 를 저장 합 니 다.
Future Task 패키지 Future 의 실체 클래스
1.Callable 과 Runnbale 의 차이
a.Callable 이 정의 하 는 방법 은 call 이 고 Runnable 이 정의 하 는 방법 은 run 입 니 다.
b.call 방법 은 반환 값 이 있 고 run 방법 은 반환 값 이 없습니다.
c.call 방법 은 이상 을 던 질 수 있 지만 run 방법 은 이상 을 던 질 수 없습니다.
2、Future
Future 는 비동기 계산 결 과 를 나타 내 는데 다음 과 같은 방법 을 제공 했다.주로 임무 의 완성 여 부 를 판단 하고 임 무 를 중단 하 며 임무 수행 결 과 를 얻 는 것 이다.

public interface Future<V> {
 
   boolean cancel(boolean mayInterruptIfRunning);
 
   boolean isCancelled();
 
   boolean isDone();
 
   V get() throws InterruptedException, ExecutionException;
 
   V get(long timeout, TimeUnit unit)
     throws InterruptedException, ExecutionException, TimeoutException;
 }
3、FutureTask
취소 가능 한 비동기 계산 은 Future 에 대한 기본 적 인 실현 을 제공 합 니 다.계산 이 완료 되 었 을 때 만 결 과 를 얻 을 수 있 습 니 다.계산 이 완료 되 지 않 으 면 get 방법 을 차단 합 니 다.

public class FutureTask<V> implements RunnableFuture<V>

public interface RunnableFuture<V> extends Runnable, Future<V>
Future Task 는 Future 인터페이스 뿐만 아니 라 Runnable 인터페이스 도 실현 하기 때문에 Future Task 를 하나의 임무 로 Executor 에 맡 길 수 있 을 뿐만 아니 라 Thread 를 통 해 스 레 드 를 만 들 수 있 습 니 다.
Callable 과 Future Task
callable 작업 정의:

public class MyCallableTask implements Callable<Integer>
 {
   @Override
   public Integer call()
     throws Exception
   {
     System.out.println("callable do somothing");
     Thread.sleep(5000);
     return new Random().nextInt(100);
   }
 }

public class CallableTest
 {
   public static void main(String[] args) throws Exception
   {
     Callable<Integer> callable = new MyCallableTask();
     FutureTask<Integer> future = new FutureTask<Integer>(callable);
     Thread thread = new Thread(future);
     thread.start();
     Thread.sleep(100);
     //           
     future.cancel(true);
     //              
     System.out.println("future is cancel:" + future.isCancelled());
     if(!future.isCancelled())
     {
       System.out.println("future is cancelled");
     }
     //         
     System.out.println("future is done:" + future.isDone());
     if(!future.isDone())
     {
       System.out.println("future get=" + future.get());
     }
     else
     {
       //     
       System.out.println("task is done");
     }
   }
 }
실행 결과:

callable do somothing
future is cancel:true
future is done:true
task is done
이 DEMO 는 주로 Future Task 의 상태 설정 을 호출 하 는 방법 으로 상태의 변 화 를 보 여 줍 니 다.
a.11 번 째 줄 에서 작업 수행 을 취소 하려 고 시도 합 니 다.이 방법 은 작업 이 완료 되 었 고 취소 되 었 으 면 false 로 돌아 갑 니 다.아직 완성 되 지 않 은 작업 을 취소 할 수 있다 면 true 로 돌아 갑 니 다.이 DEMO 에 서 는 작업 이 휴면 상태 이기 때문에 취소 할 수 있 습 니 다.

future.cancel(true);
b.제1 3 줄,퀘 스 트 취소 성공 여 부 를 판단 합 니 다.퀘 스 트 가 정상적으로 완성 되 기 전에 취소 하면 true 로 돌아 갑 니 다.

System.out.println("future is cancel:" + future.isCancelled());
c.제1 9 행,임무 의 완성 여 부 를 판단 합 니 다.만약 에 임 무 를 완성 하면 true 로 돌아 갑 니 다.다음 과 같은 몇 가지 상황 은 모두 임무 완성 에 속 합 니 다.정상 적 인 종료,이상 또는 취소 로 완성 합 니 다.
우리 의 데모 에서 임 무 는 취소 로 인해 완성 되 었 다.

 System.out.println("future is done:" + future.isDone());
d.22 번 째 줄 에서 비동기 스 레 드 가 실 행 된 결 과 를 얻 습 니 다.저 는 이 DEMO 에서 여기까지 실행 되 지 않 았 습 니 다.주의해 야 할 것 은 future.get 방법 은 현재 스 레 드 를 막 고 작업 이 실 행 될 때 까지 결 과 를 되 돌려 줄 것 입 니 다.

System.out.println("future get=" + future.get());
Callable 과 Future

public class CallableThread implements Callable<String>
{
  @Override
  public String call()
    throws Exception
  {
    System.out.println("  Call  ,    ,     :" + System.currentTimeMillis());
    Thread.sleep(10000);
    return "    ";
  }

  public static void main(String[] args) throws Exception
  {
    ExecutorService es = Executors.newSingleThreadExecutor();
    Callable<String> call = new CallableThread();
    Future<String> fu = es.submit(call);
    es.shutdown();
    Thread.sleep(5000);
    System.out.println("     5 ,    " + System.currentTimeMillis());
    String str = fu.get();
    System.out.println("Future     ,str=" + str + ";     :" + System.currentTimeMillis());
  }
}
실행 결과:

  Call  ,    ,     :1478606602676
     5 ,    1478606608676
Future     ,str=    ;     :1478606612677
이곳 의 future 는 스 레 드 탱크 에 직접 던 져 서 실 행 했 습 니 다.작업 의 실행 결 과 를 인쇄 해 야 하기 때문에 실행 결 과 를 보면 메 인 스 레 드 는 5s 휴면 을 했 지만 Call 방법 에서 작업 의 결 과 를 얻 을 때 까지 중간 시간 차 는 10s 입 니 다.get 방법 은 작업 이 완 료 될 때 까지 현재 스 레 드 를 막 을 수 있 음 을 설명 합 니 다.
Future Task 를 통 해서 도 같은 효 과 를 얻 을 수 있 습 니 다:

public static void main(String[] args) throws Exception
  {
   ExecutorService es = Executors.newSingleThreadExecutor();
   Callable<String> call = new CallableThread();
   FutureTask<String> task = new FutureTask<String>(call);
   es.submit(task);
   es.shutdown();
   Thread.sleep(5000);
   System.out.println("     5 ,     :" + System.currentTimeMillis());
   String str = task.get();
   System.out.println("Future     ,str=" + str + ";     :" + System.currentTimeMillis());
  }
이상 의 조합 은 우리 에 게 이러한 변 화 를 가 져 다 줄 수 있다.
만약 에 한 장면 에서 방법 A 가 한 데 이 터 를 되 돌려 주 려 면 10s 가 필요 하고 A 방법 뒤의 코드 운행 은 20s 가 필요 하지만 이 20s 의 실행 과정 에서 뒤의 10s 만 방법 A 가 실행 한 결과 에 의존한다.예전 과 같이 동기 화 방식 을 사용 하면 반드시 10s 의 시간 이 낭비 되 고 앞의 두 가지 조합 을 사용 하면 효율 이 높아진다.
1.먼저 A 방법의 내용 을 Callable 실현 류 의 call()방법 에 넣 습 니 다.
2.메 인 스 레 드 에서 스 레 드 풀 을 통 해 A 작업 수행
3,실행 후 방법 중 10 초 방법 A 실행 결과 에 의존 하지 않 는 코드
4.방법 A 의 실행 결 과 를 얻 고 다음 방법 중 10 초 의존 방법 A 실행 결과 의 코드 를 실행 합 니 다.
이렇게 코드 의 집행 효율 이 단번에 높 아 졌 으 니 프로그램 은 A 방법 에 걸 릴 필요 가 없다.
읽 어 주 셔 서 감사합니다. 여러분 에 게 도움 이 되 기 를 바 랍 니 다.본 사이트 에 대한 여러분 의 지지 에 감 사 드 립 니 다!

좋은 웹페이지 즐겨찾기