[Multithreading] three Callable high concurrent programming source code analysis

Program ape Society of GitHub, welcome Star
https://github.com/ITfqyd/cxyxs
This article has been recorded to github, to form the corresponding topics.

Foreword

By the last chapter there are several ways to achieve multi-threaded, multi-threaded way we have learned to achieve. However, in general we know it are two kinds of inheritance Thread class and implement runnable interfaces. Callable interface for multi-threading very strange , we look through the source code to learn, to understand how it is callable.

1.Callable Past and Present

Runnable interface or inherit Thread to achieve a multi-threaded through, we want to get the results of running threads, you can get by way of shared variables. To solve this problem, java in jdk1.5 introduced in callable, Future interface.

1.1 Callable Past Runnable

package com.cxyxs.thread.three;

import java.util.Date;

/**
 * Description:转发请注明来源  程序猿学社 - https://ithub.blog.csdn.net/
 * Author: 程序猿学社
 * Date:  2020/2/17 21:43
 * Modified By:
 */
public class MyThreadRunnable implements Runnable{
    //测试账号
    private int count=0;
    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            try {
                Thread.sleep(1000);
                count++;
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        MyThreadRunnable run = new MyThreadRunnable();
        Thread thread = new Thread(run);
        thread.start();
        try {
            //等待线程执行完毕,不然获取不到最终的结果
            thread.join();
            System.out.println(run.count);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

Test Results

Here Insert Picture Description

  • In this way, we are not achieved, the results get thread. Now we summarize the way through runnable, it is how to obtain the return of multi-threaded interface.
  • Define a class that implements Runnable interface defines a member variable to receive the run method, and the result we need.
  • When called, the class is instantiated as a parameter passed Thread, the start method is called a thread start
  • join method calling thread, waiting thread is finished, so that we can get the results after the implementation of the 5 threads, or is 0.

1.2 Callable of life

By calling FutureTask + Thread

package com.cxyxs.thread.three;

import java.util.Date;
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;

/**
 * Description:转发请注明来源  程序猿学社 - https://ithub.blog.csdn.net/
 * Author: 程序猿学社
 * Date:  2020/2/19 0:12
 * Modified By:
 */
public class MyThreadCallable {
    public static void main(String[] args) throws Exception{
        //第一步
        Callable<Integer> callable = new Callable<Integer>() {
            @Override
            public Integer call() throws Exception {
                int count=0;
                for (int i = 0; i < 5; i++) {
                        Thread.sleep(1200);
                    count++;
                }
                return count;
            }
        };

        FutureTask<Integer> task = new FutureTask<>(callable);

        Thread thread = new Thread(task);
        thread.start();

        Integer result = task.get();
        System.out.println("获取多线程的值:"+result);
    }
}
  • To be lazy, here abbreviated first step, and are generally class implements the Callable interface rewrite the call, using the shorthand method I am here.
  • Examples of a FutureTask, a, to achieve Callable classes, as the shape parameter passed into the constructor.
  • Examples of a thread, the object FutureTask as shaped configuration parameter passing method.
  • Call the get method FutureTask object. You can get the value.

ExecutorService + Future call implementation

 public void two() throws Exception{
        Callable<Integer> callable = new Callable<Integer>() {
            @Override
            public Integer call() throws Exception {
                int count=0;
                for (int i = 0; i < 5; i++) {
                    Thread.sleep(1200);
                    count++;
                }
                return count;
            }
        };

        ExecutorService e= Executors.newFixedThreadPool(10);
        Future<Integer> f1=e.submit(callable);
        Integer result = f1.get();
        System.out.println("获取多线程的值:"+result);
    }

Recommends using this method, the thread pool managed by multiple threads.
Begs the question, why use a thread pool?
In order to reduce the number of creating and destroying threads, each thread can be used multiple times.
Here you can understand. I know such a thing. There will be follow-up related articles related presentations thread pool.
Here Insert Picture Description

2. Source analysis

He did not talk much, just as we have just summed up by a multi-step how to implement Callable thread. We analyze the way + Future ExecutorService call implementation , let's start step by step to get to see his source. Have the leisure of a fraternity, you can try to see their own source FutureTask + Thread this way call.

2.1 The first step to achieve Callable Interface

Callable Interface

@FunctionalInterface
public interface Callable<V> {
    /**
     * Computes a result, or throws an exception if unable to do so.
     *
     * @return computed result
     * @throws Exception if unable to compute a result
     */
    V call() throws Exception;
}

Runnable Interface

@FunctionalInterface
public interface Runnable {
    public abstract void run();
}

After reading the source code, you Rotarians can talk about the difference between Callable and Runnable interface it?

  • Different method name, Callable is call, Runnable is run
  • Callable method, Runnable is an abstract method
  • Callable exception is thrown, Runnable not throw an exception
  • Callable return value V, Runnable no return value.
  • Callable can define a generic, when we called via get, you do not need unpacking boxes.
    While throwing an exception and returns a value, that is a very important Callable advantage, that is, to solve the problem Runnable some of the pain points.

2.2 FutureTask class structure in FIG.

First, let's look at the class structure futureTask. Right idea, select digrams-> Show digrams ( idea version )
Here Insert Picture Description
by this map, we can see the relationship corresponding to a good, C indicates the class, I is the interface
@FunctionalInterface a function interface.
According to us this figure, one by one, source-analysis.
By chart, we can see FutureTask achieved RunnableFuture interfaces, let us take a closer look.

2.3 RunableFuture Interface

public interface RunnableFuture<V> extends Runnable, Future<V> {
    /**
     * Sets this Future to the result of its computation
     * unless it has been cancelled.
     */
    void run();
}

See here, before we will know why we say Callable is plus version of Runnable. In fact, some optimization is done on the basis of Runnable.

2.4 Runnable Interface

@FunctionalInterface
public interface Runnable {
    public abstract void run();
}

Before addressing this because there are too, too much is not described here.

2.5 Future Interface

By all the methods in the class or interface view (idea using alt + 7)
Here Insert Picture Description

  • cancel method: Calculation not finished, the calculation process can be canceled,
  • isCancelled method: whether to cancel
  • isDone method: completion
  • get method: get results (if not finished computing, also must wait)
  • get (long, TimeUnit) get the results, you can specify a timeout, if within the specified time, no results are returned, will throw an exception of a TimeOutException

2.6 FutureTask source code analysis

FutureTask task = new FutureTask<>(callable);
Through the code, we find that we call the constructor of FutureTask, the callable object instances, as parameter, passing into slightly.

   public FutureTask(Callable<V> callable) {
        if (callable == null)
            throw new NullPointerException();
        this.callable = callable;
        this.state = NEW;       // ensure visibility of callable
    }

If you do not pass Callable throw NullPointerException. We found that there is a state variable value NEW

/*
     * Possible state transitions:
     * NEW -> COMPLETING -> NORMAL
     * NEW -> COMPLETING -> EXCEPTIONAL
     * NEW -> CANCELLED
     * NEW -> INTERRUPTING -> INTERRUPTED
     */
    private volatile int state;
    private static final int NEW          = 0;
    private static final int COMPLETING   = 1;
    private static final int NORMAL       = 2;
    private static final int EXCEPTIONAL  = 3;
    private static final int CANCELLED    = 4;
    private static final int INTERRUPTING = 5;
    private static final int INTERRUPTED  = 6;
  • NEW (initialization)
  • COMPLETING (operation)
  • NORMAL (completed state)
  • EXCEPTIONAL (task due to abnormal end)
  • CANCELLED (not yet run on the call cancel (true) method to cancel)
  • INTERRUPTING (running in on calls cancel (true) method is canceled)
  • An INTERRUPTED (canceled state, the INTERRUPTING converted into an INTERRUPTED)
    source comment section, is the change in the status of several tasks.

FutureTask usually directly subject, as a parameter to the constructor method of the Thread class incoming.
Here Insert Picture Description
NEW Under normal circumstances -> COMPLETING -> NORMAL
call new FutureTask the status to New
calls the run method FutureTask changed COMPLETING
halfway is not unusual, after executing the run method, it will return to NORMAL

  • Call task.get can get the results of threads of execution
 public V get() throws InterruptedException, ExecutionException {
        int s = state;
        if (s <= COMPLETING)
            s = awaitDone(false, 0L);
        return report(s);
    }

COMPLETING identification operation, to determine whether this task is already in operation, is already calling the run method. Description task has not been completed, we need to wait, so here call awaitDone method.

  • The result is a method call report
private V report(int s) throws ExecutionException {
        Object x = outcome;
        if (s == NORMAL)
            return (V)x;
        if (s >= CANCELLED)
            throw new CancellationException();
        throw new ExecutionException((Throwable)x);
    }

If the status is completed (NORMAL), a direct return to operating results.

postscript

According to the president, with the understanding explore Callable source code, source code analysis is not found, it is not as difficult as we thought. Each step of source code analysis do not understand, know the ins and outs of how it is on the line.

Program ape Society of GitHub, welcome Star
https://github.com/ITfqyd/cxyxs
This article has been recorded to github, to form the corresponding topics.

Published 274 original articles · won praise 477 · Views 200,000 +

Guess you like

Origin blog.csdn.net/qq_16855077/article/details/104382709