您的位置:

深入理解callable接口

在Java开发中,线程是非常常见的一种操作。而在多线程操作中,callable接口则扮演了重要的角色。本文将从多个方面对callable接口进行详细的阐述。

一、callable接口和主线程循环输出

在java中,callable接口是一种核心接口。callable接口是一种可以返回值的多线程接口,该接口和Runnable接口类似,但是callable可以返回执行完任务后的结果。


import java.util.concurrent.*;

public class CallableDemo {

    public static void main(String[] args) {
        ExecutorService executor = Executors.newSingleThreadExecutor();
        Future
    future = executor.submit(new Task());
        try {
            while (!future.isDone()) {
                System.out.println("Task is not yet completed....");
                Thread.sleep(1);
            }
            System.out.println("Task completed.\nRetrieved result is " + future.get());
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }
    }

    static class Task implements Callable
     {

        @Override
        public Integer call() throws Exception {
            int sum = 0;
            for (int i = 0; i < 100; i++) {
                sum += i;
            }
            return sum;
        }
    }
}

    
   

在上述代码中,我们使用了ExecutorService.submit()方法,并传递了实现了Callable接口的Task对象。我们可以看到,该程序会先打印出"Task is not yet completed....",然后在获取返回值之前,每隔1毫秒打印一次。这表明主线程正在等待任务完成。一旦任务完成并且返回结果,程序会打印出"Task completed. Retrieved result is 4950"。

二、线程callable接口创建

接下来,我们将要学习如何在Java中创建callable接口的线程。


import java.util.concurrent.Callable;

public class CallableTask implements Callable
    {

    private final String taskName;

    public CallableTask(String taskName) {
        this.taskName = taskName;
    }

    @Override
    public String call() throws Exception {
        Thread.sleep(100);
        return "Task " + taskName + " is complete.";
    }
}

   

在上述代码中,我们创建了一个实现了callable接口的CallableTask对象。该对象需要在call()方法中提供返回值。在本例中,返回值是一个字符串,表示任务已完成。输出语句是在该方法中控制的。

三、callable接口使用

1、callable接口返回值是什么

Callable接口的返回值可以是任意类型的对象。在上个示例中,返回了一个字符串。因此,通常情况下,开发人员需要根据任务的需求来选择返回值类型。

2、callable接口如何循环

在下面的示例中,我们将演示如何在Java中使用Callable接口来运行一个无限循环的任务。当控制台读取到大写字母Q时,程序会退出。


import java.util.Scanner;
import java.util.concurrent.Callable;

public class LoopTask implements Callable
    {

    @Override
    public Void call() throws Exception {
        Scanner scanner = new Scanner(System.in);
        while (true) {
            System.out.println("Enter a command (Q to quit): ");
            String command = scanner.nextLine();
            if ("Q".equalsIgnoreCase(command)) {
                break;
            }
            System.out.println("Command " + command + " is not recognized.");
        }
        System.out.println("Loop task completed!");
        return null;
    }
}

   

在上述代码中,我们创建了一个名为LoopTask的类。在该类中,我们实现了callable接口,并且使用了Scanner类读取控制台输入。在循环结束之后,控制台会显示"Loop task completed!"消息。

3、callable接口创建线程

在下面的示例中,我们将演示如何使用Java中的callable接口创建线程。


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

public class ThreadDemo {

    public static void main(String[] args) throws InterruptedException, ExecutionException {
        ExecutorService executor = Executors.newSingleThreadExecutor();
        Future
    future = executor.submit(new Callable
    () {
            @Override
            public Integer call() throws Exception {
                return 1 + 2;
            }
        });
        System.out.println("Result: " + future.get());
        executor.shutdown();
    }
}

    
   

在上述代码中,我们创建了一个Callable 对象,并将其传递给ExecutorService.submit()方法。该对象可以返回一个整型值,并将其返回给主线程。在示例中,我们将获取的返回值输出到控制台。

4、callable接口实现多线程

下面的示例演示了如何使用Java中的Callable接口实现多线程。


import java.util.concurrent.*;

public class MultiThreadDemo {

    public static void main(String[] args) throws InterruptedException, ExecutionException {
        ExecutorService executor = Executors.newFixedThreadPool(5);
        Future
   [] futureTasks = new Future[5];
        for (int i = 0; i < 5; i++) {
            Callable
     task = new CallableImpl();
            futureTasks[i] = executor.submit(task);
        }
        for (int i = 0; i < futureTasks.length; i++) {
            if (futureTasks[i].isDone()) {
                String result = futureTasks[i].get();
                System.out.println("Result: " + result);
            }
        }
        executor.shutdown();
    }

    static class CallableImpl implements Callable
      {

        @Override
        public String call() throws Exception {
            Thread.sleep(1000);
            return Thread.currentThread().getName();
        }
    }
}

     
    
   

在上述代码中,我们使用了Executors.newFixedThreadPool()方法,该方法会创建一个最多包含5个线程的线程池。我们然后使用一个for循环创建了5个实现了callable接口的CallableImpl对象,并将其传递给ExecutorService.submit()方法。在接下来的for循环中,我们使用Future.get()方法获取Future对象的结果。在本例中,我们输出了执行每个任务的线程的名称。

5、callable接口如何使用循环

下面的示例演示了如何使用Java中的Callable接口和循环。


import java.util.concurrent.*;

public class LoopCallableDemo {

    public static void main(String[] args) {
        ExecutorService executor = Executors.newSingleThreadExecutor();
        Future
    future = executor.submit(new LoopTask());
        try {
            while (!future.isDone()) {
                System.out.println("Task is not yet completed....");
                Thread.sleep(1000);
            }
            System.out.println("Task completed.\nRetrieved result is " + future.get());
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }
        executor.shutdown();
    }

    static class LoopTask implements Callable
     {

        @Override
        public String call() throws Exception {
            int count = 0;
            for (int i = 0; i < 10; i++) {
                count++;
                Thread.sleep(1000);
            }
            return "Task completed - iterations performed: " + count;
        }
    }
}

    
   

在上述代码中,我们使用了一个实现了Callable 接口的LoopTask对象。在call()方法中,我们使用了一个for循环,在循环结束时返回了一个包含执行次数的字符串。在main()方法中,我们使用了ExecutorService.submit()方法,将实现了LoopTask的Callable对象传递给了该方法。

四、callable接口是线程安全的吗

callable接口是线程安全的,因为每次调用call()方法时都会创建一个新的实例。每个调用都是独立的,不会对其他线程造成影响。因此,无需担心在多线程应用程序中使用callable接口会出现线程安全问题。

五、callable接口的线程通信

在Java中,callable接口的线程通信可以通过使用Future接口实现。


import java.util.concurrent.*;

public class ThreadCommunicationDemo {

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        ExecutorService executor = Executors.newSingleThreadExecutor();
        Future
    future = executor.submit(new Task());
        while (!future.isDone()) {
            System.out.println("Task is not yet completed");
            Thread.sleep(500);
        }
        int result = future.get();
        System.out.println("Task is completed, result: " + result);
        executor.shutdown();
    }

    static class Task implements Callable
     {

        @Override
        public Integer call() throws Exception {
            Thread.sleep(2000);
            return 100;
        }
    }
}

    
   

在上述代码中,我们使用了ExecutorService.submit()方法来执行Task对象。在接下来的while循环中,我们使用了Future.isDone()方法,来检查Task对象是否已经完成。一旦任务完成,我们可以使用Future.get()方法来获取Future对象的结果,并将其输出到控制台。

总结

以上就是本文对callable接口的详细阐述。通过本文,我们了解了callable接口和主线程循环输出、线程callable接口创建,callable接口返回值是什么、callable接口如何循环、callable接口创建线程,callable接口实现多线程、callable接口如何使用循环、callable接口是线程安全的吗、callable接口的线程通信等知识。希望对读者有所帮助。