天天看點

記錄一下5種實作異步方法調用的Controller

作者:浮雲翌日

1:使用Callable的異步調用

@GetMapping("/call")
	public Callable<String> call() {
		log.info("getResult");
		Callable<String> callable = new Callable<String>() {
			@Override
			public String call() throws Exception {
				return "success";
			}
		};
		return callable;
	}           

2:使用DeferredResult的異步方法,逾時傳回預設資訊

@GetMapping("/get")
	public DeferredResult<ResponseMsg<String>> get() {
		log.info("getResult");
		DeferredResult<ResponseMsg<String>> result = new DeferredResult<>(OUT_OF_TIME, response);

		result.onTimeout(() -> {
			log.info("調用逾時");
		});

		result.onCompletion(() -> {
			log.info("調用完成");
		});

		// 并發,加鎖
		synchronized (taskQueue) {
			taskQueue.put(result);
		}

		return result;
	}
            

TaskQueue類

@Slf4j
@Component
public class TaskQueue {

	private static final int QUEUE_LENGTH = 10000;

	private BlockingQueue<Task> queue = new LinkedBlockingDeque<>(QUEUE_LENGTH);

	// take put會阻塞隊列;

	// offer 是帶時間參數的add;

	// poll 是帶時間參數的peek;

	private AtomicLong atom = new AtomicLong(0);

	/*
		public void put(DeferredResult<ResponseMsg<String>> result){
			Long taskId = atom.incrementAndGet();
			log.info("任務加入隊列,id為:{}", taskId);
			queue.offer(new Task(taskId, result));
		}
	
		public Task take() {
			Task task = queue.poll();
			log.info("獲得任務:{}", task);
			return task;
		}
		*/
	public void put(DeferredResult<ResponseMsg<String>> result) {
		Long taskId = atom.incrementAndGet();
		log.info("任務加入隊列,id為:{}", taskId);
		try {
			queue.put(new Task(taskId, result));
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

	public Task take() {
		Task task = null;
		try {
			task = queue.take();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		log.info("獲得任務:{}", task);
		return task;
	}

}
           

3:使用WebAsyncTask異步任務,其中需要實作線程排程

@GetMapping("/async")
	public WebAsyncTask<String> async() {
		WebAsyncTask<String> webAsyncTask = new WebAsyncTask<String>(1000, new Callable<String>() {
			@Override
			public String call() throws Exception {
				// 業務邏輯處理
				Thread.sleep(5000);
				String message = "username:wangbinghua";
				return message;
			}
		});
		webAsyncTask.onCompletion(new Runnable() {
			@Override
			public void run() {
				System.out.println("調用完成");
			}
		});
		webAsyncTask.onTimeout(new Callable<String>() {
			@Override
			public String call() throws Exception {
				System.out.println("業務處理逾時");
				return "<h1>Time Out</h1>";
			}
		});

		return webAsyncTask;
	}           

4:CompletionStage異步調用

@GetMapping(path = "/search")
	public CompletionStage<List<String>> search() {
		CompletionStage<List<String>> result = CompletableFuture.completedFuture(List.of("success", "error"));
		/*
		 * try { List<String> lists=result.toCompletableFuture().get(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch
		 * (ExecutionException e) { // TODO Auto-generated catch block e.printStackTrace(); }
		 */
		return result;
	}           

5:ListenableFuture,不過此類已經被标記為過時了。使用CompletableFuture代替

@RequestMapping(value = "/list")
	public ListenableFuture<String> list() {
		ListenableFutureTask<String> ListenableFuture = new ListenableFutureTask<>(() -> {
			return String.valueOf(System.currentTimeMillis());
		});
		Executors.newSingleThreadExecutor().submit(ListenableFuture);
		return ListenableFuture;
	}           

換成CompletableFuture

public CompletableFuture<String> complete() {
        CompletableFuture<String> completableFuture = CompletableFuture.supplyAsync(() -> {
            return String.valueOf(System.currentTimeMillis());
        });
        return completableFuture;
    }           

繼續閱讀