The coder is on the ropes

Life is a process of baptism itself, the baptism is not in the traditional sense of the baptism, baptism in the traditional sense is generally thought that this man’s thoughts get baptism, the soul get baptism, very pure and fresh and free from vulgarity, not sophisticated, not smooth, the baptism of the reality actually is to let a person shed childish, faded ignorance, let you become bow, sleek sophistication, we are all animals, Need material satisfaction, more need desire to fill, so, become their childhood spit on the object is understandable, but this is a choice, you can choose, but in the era of material desire, most people do not have the power of this choice!

The Future and FutureTask

Future is an interface, and FutureTask is a class that implements the RunnableFuture interface, which inherits the Future interface.

Methods of the Future interface

V get() : Gets the result of the asynchronous execution. If no result is returned, this method blocks until the asynchronous calculation is complete.

V GET (Long timeout, TimeUnit Unit) : Gets the result of asynchronous execution. If no result is available, this method will block, but there is a time limit. If the blocking time exceeds the specified timeout period, this method will throw an exception.

Boolean isDone() : Returns true if the task is finished, whether it was canceled or an exception occurred.

Boolean isCancelled() : returns true if the task isCancelled before completion.

Boolean Cancel (Boolean mayInterruptRunning) : Perform cancel(…) if the task has not yet started. Method will return false; If the task has already started, executing the cancel(true) method attempts to stop the task by interrupting the thread executing the task, and returns true on success; When the task has been started, executing the cancel(false) method will not affect the thread of the executing task (allowing the thread to execute until completion), and returns false; When the task is complete, cancel(…) Method will return false. The mayInterruptRunning parameter indicates whether the executing thread is interrupted.

Future is an interface, so we can’t create objects directly, we need to work with thread pools, and FutureTask we can create objects directly.

The use of the Future

Future represents the result of asynchronous execution, that is, after the asynchronous execution, the result is stored in the Future. When we use the thread pool submit(), we need to pass in the Callable interface. The return value of the thread pool is a Future, and the Future stores the execution result. The result can be retrieved via the Future’s get() method. If the thread pool uses execute(), the Runnable interface is passed with no return value.

Place the order with the following we use the Future simulation operation, the user order store order information, after deducting the inventory, increase integral, send text messages, so multiple tasks if use synchronous implementation, then efficiency will be lower, the user experience is not good, usually we will use a message queue to achieve asynchronous effect, today we don’t have the message queue, Instead, use the Future interface to implement asynchrony.

public class FutureTest {
    final static ExecutorService threadPool = Executors.newCachedThreadPool();
​
    // Save the order task
    public static Future<R> saveOrderTask(OrderInfo orderInfo) {
        return threadPool.submit(new Callable<R>() {
            @Override
            public R call(a) throws Exception {
                returnsaveOrder(orderInfo); }}); }// Subtract inventory tasks
    public static Future<R> decreaseStockTask(OrderInfo orderInfo) {
        return threadPool.submit(new Callable<R>() {
            @Override
            public R call(a) throws Exception {
                returndecreaseStockByCommodityId(orderInfo); }}); }// Add integral tasks
    public static Future<R> increaseIntegralTask(OrderInfo orderInfo) {
        return threadPool.submit(new Callable<R>() {
            @Override
            public R call(a) throws Exception {
                returnincreaseIntegralByUserId(orderInfo); }}); }public static void sendMsgToPhone(OrderInfo orderInfo) {
        threadPool.execute(new Runnable() {
            @Override
            public void run(a) {
                System.out.println("User [" + orderInfo.getUserId() + "】, you have placed your order ~~~~~~~~"); }}); }// Add integral RPC interface
    public static R increaseIntegralByUserId(OrderInfo orderInfo) {
        System.out.println("Increase points ~~~~~~~~");
        integralService.increaseIntegralByUserId(orderInfo.getUserId(),20);
        return new R(200."Credit added successfully".null);
    }
​
    // Subtract the inventory RPC interface
    public static R decreaseStockByCommodityId(OrderInfo orderInfo) {
        System.out.println("Inventory deduction ~~~~~~~~");
        stockService.decreaseStockByCommodityId(orderInfo.getCommodityId());
        return new R(200."Inventory reduction succeeded".null);
    }
​
    // Save the order RPC interface
    public static R saveOrder(OrderInfo orderInfo) throws InterruptedException {
        System.out.println("Save order ~~~~~~~~");
        Thread.sleep(2000);
        orderService.insert(orderInfo);
        return new R(200."Order saved successfully".null);
    }
​
​
    public static void main(String[] args) throws ExecutionException, InterruptedException, TimeoutException {
        OrderInfo orderInfo = new OrderInfo().setId("123455").setUserId("111111").setCommodityId("123321");
        Future<R> orderTask = saveOrderTask(orderInfo);
        Future<R> stockTask = decreaseStockTask(orderInfo);
        Future<R> integralTask = increaseIntegralTask(orderInfo);
        sendMsgToPhone(orderInfo);
        if (orderTask.get().getCode() == 200 && orderTask.isDone()) 
            System.out.println(orderTask.get().getMsg());
        if (stockTask.get().getCode() == 200 && stockTask.isDone()) 
            System.out.println(stockTask.get().getMsg());
        if (integralTask.get().getCode() == 200&& integralTask.isDone()) System.out.println(integralTask.get().getMsg()); threadPool.shutdownNow(); }}Copy the code

The output

Save orders ~ ~ ~ ~ ~ ~ ~ ~ deduct inventory ~ ~ ~ ~ ~ ~ ~ ~ increase integral ~ ~ ~ ~ ~ ~ ~ ~ user [111111], you have order success ~ ~ ~ ~ ~ ~ ~ ~ the order successful deductions inventory increase integral successCopy the code

It took us 2s to simulate the business operation in the order saving interface. As can be seen from the output result, other RPC interfaces did not block when the order was saved, but executed at the same time, thus achieving the asynchronous effect.

However, we found a problem, that is, the asynchronous return result was blocked. It was clear that the interface of deducting inventory and increasing credits would return soon, but it was found in the output that the interface of deducting inventory and increasing credits were output after saving the order, so we can seeFutureBlocks the return result.

So instead of using the Future, we use the Runnable interface instead of the Callable interface. Execute () instead of submit()

Execute () and submit()

1. Execute does not return a value, so you cannot know whether the task is successfully executed. Submit returns a value. 2. Execute cannot handle and catch exceptions after throwing an exception, while Submit can catch exceptions.

The use of FutureTask

FutureTask is the implementation class of the Future interface, we can directly create a FutureTask object, below we change the order process above, use FutureTask to achieve.

/ * * *@authorLiu brand *@date2022/3/26 17:34 * /
public class PlaceOrderFutureTaskTest {
    final static ExecutorService threadPool = Executors.newCachedThreadPool();
​
    // Save the order task
    public static FutureTask<R> saveOrderTask(OrderInfo orderInfo){
        return new FutureTask<>(new Callable<R>() {
            @Override
            public R call(a) throws Exception {
                returnsaveOrder(orderInfo); }}); }// Subtract inventory tasks
    public static FutureTask<R> decreaseStockTask(OrderInfo orderInfo){
        return new FutureTask<>(new Callable<R>() {
            @Override
            public R call(a) throws Exception {
                returndecreaseStockByCommodityId(orderInfo); }}); }// Add integral tasks
    public static FutureTask<R> increaseIntegralTask(OrderInfo orderInfo){
        return new FutureTask<>(new Callable<R>() {
            @Override
            public R call(a) throws Exception {
                returnincreaseIntegralByUserId(orderInfo); }}); }public static void sendMsgToPhone(OrderInfo orderInfo){
        threadPool.execute(new Runnable() {
            @Override
            public void run(a) {
                System.out.println("User ["+orderInfo.getUserId()+"】, you have placed your order ~~~~~~~~"); }}); }// Add integral RPC interface
    public static R increaseIntegralByUserId(OrderInfo orderInfo){
        System.out.println("Increase points ~~~~~~~~");
        integralService.increaseIntegralByUserId(orderInfo.getUserId(),20);
        return new R(200."Credit added successfully".null);
    }
​
    // Subtract the inventory RPC interface
    public static R decreaseStockByCommodityId(OrderInfo orderInfo){
        System.out.println("Inventory deduction ~~~~~~~~");
        stockService.decreaseStockByCommodityId(orderInfo.getCommodityId());
        return new R(200."Inventory reduction succeeded".null);
    }
​
    // Save the order RPC interface
    public static R saveOrder(OrderInfo orderInfo) throws InterruptedException {
        System.out.println("Save order ~~~~~~~~");
        Thread.sleep(2000);
        orderService.insert(orderInfo);
        return new R(200."Order saved successfully".null);
    }
    
    public static void main(String[] args) throws ExecutionException, InterruptedException, TimeoutException {
        OrderInfo orderInfo = new OrderInfo().setId("123455").setUserId("111111").setCommodityId("123321");
        FutureTask<R> orderTask = saveOrderTask(orderInfo);
        FutureTask<R> stockTask = decreaseStockTask(orderInfo);
        FutureTask<R> integralTask = increaseIntegralTask(orderInfo);
        threadPool.submit(orderTask);
        threadPool.submit(stockTask);
        threadPool.submit(integralTask);
        sendMsgToPhone(orderInfo);
        if (orderTask.get().getCode() == 200 && orderTask.isDone()) 
            System.out.println(orderTask.get().getMsg());
        if (stockTask.get().getCode() == 200 && stockTask.isDone()) 
            System.out.println(stockTask.get().getMsg());
        if (integralTask.get().getCode() == 200&& integralTask.isDone()) System.out.println(integralTask.get().getMsg()); threadPool.shutdownNow(); }}Copy the code

The output

Save orders ~ ~ ~ ~ ~ ~ ~ ~ deduct inventory ~ ~ ~ ~ ~ ~ ~ ~ increase integral ~ ~ ~ ~ ~ ~ ~ ~ user [111111], you have order success ~ ~ ~ ~ ~ ~ ~ ~ the order successful deductions inventory increase integral successCopy the code

There is no difference in the code, just a different way of writing the interface and implementation class. The input is the same as that of the Future, so FutureTask will block the result.

conclusion

Can be seen from the above process, the Future and FutureTask can realize asynchronous, but turned out to be synchronized, this defect is obvious, if there are any time-consuming tasks, then obtain the return value Other tasks will be blocked, can only line up slowly, under the high concurrency scenario doesn’t fit, that is there a solution? There definitely is, and that’s CompletableFuture, which we’ll cover later, but we won’t cover in this chapter.

That’s all for today, thanks for watching, and we’ll see you next time.