Runnable Callable及Future

1.Runnable

Runnable is an interface that is very simple to use:
1. Implement the interface and override the run method
2. Use an object of this class to create a thread
3. When the thread starts, the run method of the object is automatically called
It is usually used in combination with ExecutorService in development to decouple the submission of tasks from the execution of tasks, and can also better utilize the various features provided by Executor.
copy code
ExecutorService executor = Executors.newCachedThreadPool();
                   executor.submit(new Runnable() {
                        public void run() {
                               //EVERYTHING
                        }
                    });
executor.shutdown();
copy code
Compared with inheriting Thread to create threads, using Runnable allows your implementation class to implement multiple interfaces at the same time. Compared with Callable and Future, the Runnable method does not return task execution results and cannot throw exceptions
 
2.Callable
Different from Runnable, Callable is a generic parameterized interface, and can return the execution result of the thread, and can throw an exception when it cannot be calculated normally
public interface Callable<V> {
    V call() throws Exception;
}
1. Callable does not start the run method of the implementation class through the start method of Thread like Runnable, so it usually uses the submit method of ExecutorService to start the self-executing task of the call method, and the submit method of ExecutorService returns a Future type result, So Callable is usually used with Future as well
ExecutorService pool = Executors.newCachedThreadPool();
     Future<String> future = pool.submit(new Callable{
           public void call(){
                   //EVERYTHING
           }
    });
Or use FutureTask to encapsulate Callable and then start it by Thread (less used)
copy code
FutureTask<String> task = new FutureTask(new Callable{
        public void call(){
              //EVERYTHING
        }
  });
 Thead thread = new Thread(task);
 thread.start();
copy code
2. Through Executors.callbale(Runnable task, T result), you can execute Runnable and return "result", but this result is not the execution result of Runnable (the run method of Runnable is void type), but the result predefined by the executor, This can be seen from the source code of its implementation principle RunnableAdpter
copy code
public static <T> Callable<T> callable(Runnable task, T result) {
     if (task == null)
          throw new NullPointerException();
       return new RunnableAdapter<T>(task, result);//通过RunnableAdapter实现
}
    
static final class RunnableAdapter<T> implements Callable<T> {
     final Runnable task;
     final T result;
     RunnableAdapter(Runnable task, T result) {
            this.task = task;
            this.result = result;
     }
     public T call() {
        task.run();
        return result; //Return the incoming result directly
     }
   }
copy code
The difference between Runnable and Callable:
1. Runnable does not return the task execution result, Callable can return the task execution result
2. Callable throws an exception when the task cannot compute the result, while Runnable cannot
3. Runnable tasks can be executed directly by the start method of Thread or the submit method of ExecutorService
 
3.Future
Future saves the results of asynchronous calculations, can do other work when we perform tasks, and provides the following methods
* cancel(boolean mayInterruptIfRunning): Try to cancel the executing task. If the parameter is true, directly interrupt the executing task, otherwise, until the current task is executed, return true after successful cancellation, otherwise return false
* isCancel(): Determines whether the task was canceled before the normal execution, and returns true if so
* isDone(): Determine whether the task has been completed
* get(): wait for the return of the calculation result, throw if the calculation is canceled
* get(long timeout, TimeUtil unit): Set the return time of the calculation result, if the calculation result is not returned within the specified time, a TimeOutException will be thrown
Benefits of using Future:
1. Get the result of the task, judge whether the task is completed, and interrupt the task
1. The get method of Future is a good substitute for Thread.join or Thread, join(long millis)
2. The get method of Future can determine whether the execution of the program code (task) times out, such as:
try{
      future.get(60,TimeUtil.SECOND);
 }catch(TimeoutException timeout){
      log4j.log("Mission off-road, will be cancelled!!");
      future.cancel();
 }
4.FutureTask
FutureTask implements the RunnableFuture interface, providing a constructor that can use Runnable to perform tasks, and can use Future to perform tasks and obtain results, so you can use FutureTask to encapsulate Runnable or Callable objects, and then submit tasks
FutureTask(Callable<V> callable)  
 FutureTask(Runnable runnable, V result)

5. Application

Find the number of files containing a keyword: each file starts a thread to find the keyword
copy code
public class FileSearchTask {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        String path = args[0];
        String keyword = args[1];
        int c = 0;
        File[] files = new File(path).listFiles();
        ArrayList<Future<Integer>> rs = new ArrayList<>();
        for(File file: files){ //Start a task for each file to find
            MatchCount count = new MatchCount();
            count.file = file;
            count.keyword = keyword;
            FutureTask<Integer> task = new FutureTask(count);
            rs.add(task); //Add the result returned by the task to the collection
            Thread thread = new Thread(task);
            thread.start();
        }

        for(Future<Integer> f: rs){
            c += f.get(); //Iterative return results and accumulate
        }
        System.out.println("The total number of files containing keywords is: " + c);
    }
}

class  MatchCount implements Callable<Integer>{
    public File file;
    public String keyword;
    private  Integer count = 0;

    public Integer call() throws Exception { //call encapsulates the tasks that the thread needs to do
        if(search(file))
              count ++;
        return count;
    }

    public boolean search(File file){
        boolean founded = false;
        try(Scanner scanner = new Scanner(new FileInputStream(file))){
            while(!founded && scanner.hasNextLine()){
                if (scanner.nextLine().contains(keyword))
                    founded = true;
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace ();
        }
        return  founded;
    }
}
copy code

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324861420&siteId=291194637