스 레 드 노트: Future 모드


스 레 드 기술 은 우리 의 프로그램 으로 하여 금 여러 가지 일 을 동시에 할 수 있 게 합 니 다. 스 레 드 의 작업 모델 은 매우 많 습 니 다. 흔히 볼 수 있 는 모델 은 바로 사이트 의 병발 을 처리 하 는 것 입 니 다. 오늘 은 스 레 드 의 또 다른 흔 한 모델 이 라 고 말 합 니 다. 이 모델 은 전단 의 ajax 와 유사 합 니 다. 브 라 우 저 하나의 메 인 스 레 드 는 자바 script, 페이지 렌 더 링 등 작업 을 수행 합 니 다.ajax 를 사용 하여 서버 에 요청 할 때 이 과정 이 느 리 기 때문에 ajax 의 비동기 모드 는 서버 의 응답 을 기다 리 지 않 아 도 됩 니 다. 이 대기 결과 시간 에 다른 일 을 할 수 있 습 니 다. 이 모델 은 온라인 프로 세 스 기 술 력 을 Future 모드 라 고 합 니 다.
Future 모드 와 제 가 앞에서 말 한 html 5 기술 의 worker 기술 은 차이 가 많 지 않 습 니 다. 우리 프로그램 이 흐름 의 특정한 조작 을 수행 하 는 데 특히 시간 이 걸 릴 때 우 리 는 다른 스 레 드 를 만들어 서 이 번 거 로 운 시간 을 소모 하 는 임 무 를 수행 할 수 있 습 니 다. 메 인 스 레 드 는 다른 일 을 할 수 있 습 니 다. 다음은 제 가 찾 은 원생 Future 모드 를 실현 하 는 코드 입 니 다.그것 은 주로 다음 과 같다.
TestMain. java: 테스트 프로그램의 입 구 는 주로 Client 클래스 를 호출 하여 Client 에 요청 을 보 냅 니 다.
Client. java: 데이터 대상 을 되 돌려 주 고 FutureData 로 즉시 돌아 가 며 Client Thread 스 레 드 를 열 어 RealData 를 설치 합 니 다.
Data. java: 데이터 인터페이스 되 돌려 주기;
FutureData. java: Future 데이터, 구조 가 빠 르 지만 가상 데이터 로 RealData 를 설치 해 야 합 니 다.
RealData. java: 실제 데이터, 그 구 조 는 비교적 느리다.
자세 한 코드 는 다음 과 같 습 니 다.
데이터 인터페이스:
package cn.com.xSharp.futurePattern.simple;

/**
 *     
 * @author  
 *
 */
public interface Data {
	public String getData();
}

RealData 코드:
package cn.com.xSharp.futurePattern.simple;

/**
 * RealData        ,     ,   sleep   
 * @author  
 * @since 2016-06-21 21:37
 */
public class RealData implements Data {
	
	protected final String result;
	

	public RealData(String param) {
		StringBuffer sb = new StringBuffer();
		for (int i = 0;i < 10;i++){
			sb.append(param);
			try {
				Thread.sleep(100);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		result = sb.toString();
	}



	@Override
	public String getData() {
		return result;
	}

}

FutureData 코드:
package cn.com.xSharp.futurePattern.simple;

public class FutureData implements Data {
	
	protected RealData realData = null;// FutureData RealData   
	protected boolean isReady = false;
	
	public synchronized void setRealData(RealData realData){
		if (isReady){
			return;
		}
		this.realData = realData;
		isReady = true;
		notifyAll();
	}

	@Override
	public synchronized String getData() {
		while (!isReady){
			try {
				wait();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return realData.result;
	}

}

클 라 이언 트 코드:
package cn.com.xSharp.futurePattern.simple;

public class Client {

	public Data request(final String qryStr){
		final FutureData futureData = new FutureData();
		new Thread(){
			public void run(){
				RealData realData = new RealData(qryStr);
				futureData.setRealData(realData);
			}
		}.start();
		return futureData;
	}
}

TestMain 코드:
package cn.com.xSharp.futurePattern.simple;

public class TestMain {

	public static void main(String[] args) {
		Client client = new Client();
		Data data = client.request("xtq");
		System.out.println("    !");
		
		try {
			for (int i = 0;i < 12;i++){
				Thread.sleep(100);
				System.out.println("          ....");
			}
			
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		
		System.out.println("  ==:" + data.getData());
	}

}

실행 결과:
    !
          ....
          ....
          ....
          ....
          ....
          ....
          ....
          ....
          ....
          ....
          ....
          ....
  ==:xtqxtqxtqxtqxtqxtqxtqxtqxtqxtq

JDK 에 서 는 1.5 이후 전문 Future 모델 의 실현 을 제 공 했 는데 여기 서 저 는 Future Task 를 사용 하여 Future 모델 을 실현 합 니 다.
Future Task 의 JDK 문서 설명:
 
취소 가능 한 비동기 계산.계산 을 시작 하고 취소 하 는 방법, 계산 이 완 료 된 방법 을 조회 하고 계산 결 과 를 얻 는 방법 을 이용 하여 Future 에 대한 기본 적 인 실현 을 제공 합 니 다.계산 이 끝 났 을 때 만 결 과 를 얻 을 수 있 습 니 다.계산 이 완료 되 지 않 으 면 get 방법 을 차단 합 니 다.일단 계산 이 끝나 면 다시 시작 하거나 취소 할 수 없다.Future Task 를 사용 하여 Callable 또는 Runnable 대상 을 포장 할 수 있 습 니 다.FutureTask 가 Runnable 을 실 현 했 기 때문에 FutureTask 를 Executor 에 제출 하여 실행 할 수 있 습 니 다.독립 된 클래스 외 에 도 proctected 기능 을 제공 합 니 다. 사용자 정의 작업 클래스 를 만 들 때 유용 할 수 있 습 니 다.
 
다음은 그것 의 두 구조 함수 입 니 다.
FutureTask(Callable callable) 
               FutureTask,           Callable。 
FutureTask(Runnable runnable, V result) 
               FutureTask,           Runnable,         get         。

여기 서 저 는 먼저 두 번 째 구조 함수 Runnable 을 사용 하여 Future 모드 를 실현 합 니 다. 코드 는 다음 과 같 습 니 다.
package cn.com.futuretest;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;

public class FutureRunnable implements Runnable{
	private Result result;	//      ,               

	/*       */
	public FutureRunnable(Result result) {
		this.result = result;
	}

	@Override
	public void run() {
		try {
			for (int i = 0;i < 10;i++){
				Thread.sleep(100);//   100        ,             
				result.setData(result.getData() + ":" + "futureRunnable" + i);
			}						
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
	
	public static void main(String[] args) {
		Result r = new Result("xSharp");//       
		FutureRunnable futureCallable = new FutureRunnable(r);//    runnable
		FutureTask task = new FutureTask(futureCallable, r);
		//                
		ExecutorService executorService = Executors.newFixedThreadPool(1);
		//     
		executorService.execute(task);
		System.out.println("    !");
		
		try {
			for (int i = 0;i < 15;i++){
				Thread.sleep(100);
				System.out.println("          ,        " + i);
			}
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		
		try {
			System.out.println("     :" + task.get().getData());
		} catch (InterruptedException e) {
			e.printStackTrace();
		} catch (ExecutionException e) {
			e.printStackTrace();
		}finally{
			System.exit(0);
		}
		
	}

}

실행 결과: 
    !
          ,        0
          ,        1
          ,        2
          ,        3
          ,        4
          ,        5
          ,        6
          ,        7
          ,        8
          ,        9
          ,        10
          ,        11
          ,        12
          ,        13
          ,        14
     :xSharp:futureRunnable0:futureRunnable1:futureRunnable2:futureRunnable3:futureRunnable4:futureRunnable5:futureRunnable6:futureRunnable7:futureRunnable8:futureRunnable9

다음 에 저 는 Callable 인 터 페 이 스 를 사용 하여 Future Task 를 실현 합 니 다. 코드 는 다음 과 같 습 니 다.
package cn.com.futuretest;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;

public class FutureCallable implements Callable{

	private Result result;	//      ,               
	
	/*       */
	public FutureCallable(Result result) {
		this.result = result;
	}

	@Override
	public Result call() throws Exception {
		try {
			for (int i = 0;i < 10;i++){
				Thread.sleep(100);//   100        ,             
				result.setData(result.getData() + ":" + "futureCallable" + i);
			}						
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		return result;
	}
	
	public static void main(String[] args) {
		long start = System.currentTimeMillis();
		Result r = new Result("xSharp");//       
		FutureCallable callable = new FutureCallable(r);
		FutureTask task = new FutureTask(callable);
		//                
		ExecutorService executorService = Executors.newFixedThreadPool(1);
		//     
		executorService.execute(task);
		System.out.println("    !");
		long curr01 = System.currentTimeMillis();
		System.out.println("        :" + (curr01 - start) + "  ");
		try {
			for (int i = 0;i < 6;i++){
				Thread.sleep(100);
				System.out.println("          ,        " + i);
			}
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		
		try {
			System.out.println("     :" + task.get().getData());
			long end = System.currentTimeMillis();
			System.out.println("   :" + (end - start) + "  ");
		} catch (InterruptedException e) {
			e.printStackTrace();
		} catch (ExecutionException e) {
			e.printStackTrace();
		}finally{
			System.exit(0);
		}
	}

}

실행 결 과 는 다음 과 같 습 니 다.
    !
        :6  
          ,        0
          ,        1
          ,        2
          ,        3
          ,        4
          ,        5
     :xSharp:futureCallable0:futureCallable1:futureCallable2:futureCallable3:futureCallable4:futureCallable5:futureCallable6:futureCallable7:futureCallable8:futureCallable9
   :1010  

여기 서 저 는 코드 를 조 정 했 습 니 다. 하 나 는 실행 시간의 통 계 를 더 한 것 입 니 다. 하 나 는 제 가 다른 일 을 하 는 프로그램의 실행 시간 이 짧 아 지고 스 레 드 자체 가 실행 하 는 시간 보다 작 습 니 다. 이렇게 하 는 목적 은 아래 의 프로그램 과 비교 하 는 것 입 니 다. 아래 의 코드 는 제 가 스 레 드 를 실행 한 후에 다른 조작 을 하지 않 고 스 레 드 가 실 행 된 결 과 를 직접 얻 는 것 입 니 다.구체 적 인 코드 는 다음 과 같다.
package cn.com.futuretest;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;

public class NioFutureCallable implements Callable {
	
	private Result result;	//      ,               
	
	/*       */
	public NioFutureCallable(Result result) {
		this.result = result;
	}

	@Override
	public Result call() throws Exception {
		try {
			for (int i = 0;i < 10;i++){
				Thread.sleep(100);//   100        ,             
				result.setData(result.getData() + ":" + "NioFutureCallable" + i);
			}						
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		return result;
	}

	public static void main(String[] args) {
		long start = System.currentTimeMillis();
		Result r = new Result("xSharp");//       
		NioFutureCallable callable = new NioFutureCallable(r);
		FutureTask task = new FutureTask(callable);
		//                
		ExecutorService executorService = Executors.newFixedThreadPool(1);
		//     
		executorService.execute(task);
		System.out.println("    !");
		long curr01 = System.currentTimeMillis();
		System.out.println("        :" + (curr01 - start) + "  ");
		
		/*           */
		try {
			System.out.println("        :" + task.get().getData());
			long curr02 = System.currentTimeMillis();
			System.out.println("         :" + (curr02 - start) + "  ");
		} catch (InterruptedException e1) {
			e1.printStackTrace();
		} catch (ExecutionException e1) {
			e1.printStackTrace();
		}
		
		try {
			for (int i = 0;i < 10;i++){
				Thread.sleep(100);
				System.out.println("          ,        " + i);
			}
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		
		try {
			System.out.println("        :" + task.get().getData());
			long end = System.currentTimeMillis();
			System.out.println("   :" + (end - start) + "  ");
		} catch (InterruptedException e) {
			e.printStackTrace();
		} catch (ExecutionException e) {
			e.printStackTrace();
		}finally{
			System.exit(0);
		}
		

	}

}

실행 결 과 는 다음 과 같 습 니 다.
    !
        :7  
        :xSharp:NioFutureCallable0:NioFutureCallable1:NioFutureCallable2:NioFutureCallable3:NioFutureCallable4:NioFutureCallable5:NioFutureCallable6:NioFutureCallable7:NioFutureCallable8:NioFutureCallable9
         :1009  
          ,        0
          ,        1
          ,        2
          ,        3
          ,        4
          ,        5
          ,        6
          ,        7
          ,        8
          ,        9
        :xSharp:NioFutureCallable0:NioFutureCallable1:NioFutureCallable2:NioFutureCallable3:NioFutureCallable4:NioFutureCallable5:NioFutureCallable6:NioFutureCallable7:NioFutureCallable8:NioFutureCallable9
   :2012  

우 리 는 우리 가 직접 결 과 를 얻 을 때 전체 메 인 스 레 드 가 막 히 고 결과 가 돌아 온 후에 야 다음 과 같은 후속 작업 을 수행 하 는 것 을 보 았 다. 즉, 계산 이 끝나 지 않 았 다 면 우 리 는 결 과 를 얻 고 싶 었 다. 그러면 전체 실행 절차 가 막 힐 것 이다. 이런 점 은 우리 가 Future 모델 을 합 리 적 으로 사용 할 때 매우 중요 하 다.
Future Task 를 사용 하여 Future 모델 을 실현 하 는 것 외 에 우 리 는 Executor Service 의 submit 방법 으로 Future 대상 에 게 직접 돌아 갈 수 있 습 니 다. Future 는 제 가 앞에서 디자인 한 원생 Future 와 유사 합 니 다. 우리 가 호출 을 시 작 했 을 때 돌아 온 것 은 가상 결과 입 니 다. 사실은 실제 계산 이 아직 끝나 지 않 았 습 니 다. 기 다 려 야 결과 가 진정 으로 돌아 올 수 있 습 니까?코드 는 다음 과 같 습 니 다:
package cn.com.futuretest;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class RetFutureCallable implements Callable{

	private Result result;	//      ,               

	public RetFutureCallable() {
		result = new Result("xSharp");
	}

	@Override
	public Result call() throws Exception {
		try {
			for (int i = 0;i < 10;i++){
				Thread.sleep(100);//   100        ,             
				result.setData(result.getData() + ":" + "RetFutureCallable" + i);
			}						
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		return result;
	}
	
	public static void main(String[] args) {
		long start = System.currentTimeMillis();
		RetFutureCallable callable = new RetFutureCallable();
		//                
		ExecutorService executorService = Executors.newFixedThreadPool(1);
		//     
		Future r = executorService.submit(callable);
		System.out.println("    !");
		long curr01 = System.currentTimeMillis();
		System.out.println("        :" + (curr01 - start) + "  ");
		try {
			for (int i = 0;i < 6;i++){
				Thread.sleep(100);
				System.out.println("          ,        " + i);
			}
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		
		try {
			System.out.println("     :" + r.get().getData());
			long end = System.currentTimeMillis();
			System.out.println("   :" + (end - start) + "  ");
		} catch (InterruptedException e) {
			e.printStackTrace();
		} catch (ExecutionException e) {
			e.printStackTrace();
		}finally{
			System.exit(0);
		}
	}
	
	
} 

실행 결 과 는 다음 과 같 습 니 다.
    !
        :5  
          ,        0
          ,        1
          ,        2
          ,        3
          ,        4
          ,        5
     :xSharp:RetFutureCallable0:RetFutureCallable1:RetFutureCallable2:RetFutureCallable3:RetFutureCallable4:RetFutureCallable5:RetFutureCallable6:RetFutureCallable7:RetFutureCallable8:RetFutureCallable9
   :1006  

자, 본문 을 다 썼 습 니 다.

좋은 웹페이지 즐겨찾기