JAVA JUC Callable 接口

本文涉及的产品
应用实时监控服务-用户体验监控,每月100OCU免费额度
应用实时监控服务-应用监控,每月50GB免费额度
可观测监控 Prometheus 版,每月50GB免费额度
简介: 【1月更文挑战第5天】JAVA JUC Callable 接口

Callable 接口:

创建线程的多种方式:

  1. 继承Thread类
  2. 实现Runnable接口
  3. Callable接口
  4. 线程池

1.Callable接口创建线程:

目前学习了有两种创建线程的方法,一种是通过创建 Thread 类,另一种是通过使用 Runnable 创建线程,但是,Runnable 缺少的一项功能是,当线程终止时(即 run()完成时),我们无法使线程返回结果。为了支持此功能,Java 中提供了 Callable 接口:

比较Runnable接口和Callable接口:

  • Callable中的call()计算结果,如果无法计算结果,会抛出异常。
  • Runnable中的run()使用实现接口Runnable的对象创建一个线程时,启动该线程将导致在独立执行的线程中调用该对象的run方法。

总的来说:run()没有返回值,不会抛出异常。而call()有返回值,会抛出异常

2.FutureTask 实现类:

因为Thread的构造函数中没有Callable接口的参数设置,直接替换不可以,只能用下面这种线程创建方法(找一个类,即和Runnable接口有关系,又和Callable接口有关系)

发现Runnable接口有实现类FutureTask(中间对象)未来任务

FutureTask的构造函数有Callable参数,通过FutureTask创建线程对象,java.util.concurrent.FutureTask<V>

https://www.matools.com/file/manual/jdk_api_1.8_google/java/util/concurrent/FutureTask.html

使用 lambda 方式创建代码如下:

public class CallableTest {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        new Thread(()->{
            System.out.println(Thread.currentThread().getName()+"执行Runnable");
        }).start();
        FutureTask<String> task = new FutureTask<>(() -> {
            System.out.println(Thread.currentThread().getName() + "使用Callable接口");
            return "Callable接口返回值";
        });
        new Thread(task).start();
        System.out.println("Callable返回值:" + task.get());
    }
}


//比较 callable和runnable 的区别
class MyThread1 implements Runnable{
    @Override
    public void run() {
        //这里没有返回值
    }
}
class MyThread2 implements Callable{
    @Override
    public Object call() throws Exception {
        System.out.println(Thread.currentThread().getName()+"线程运行");
        return "Callable 的实现线程";  //有返回值
    }
}
public class diffentence {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        //创建 实现Runnable 的线程
        new Thread( new MyThread1(),"t1" ).start();
        //创建 实现Callable 的线程 不能直接替换 ,没有这个类型的构造方法
        // new Thread( new MyThread2(),"t2" ).start();
        //选择FutureTask 他是 Runnable 的实现类,而且构造方法含有Callable类型
        FutureTask<String>  task = new FutureTask(new MyThread2());
        new Thread(task,"hhh").start();
        System.out.println("返回值"+task.get()); //调用里面的返回值
    }
}

源码解析:

进入FutureTask底层源码可以看到它的构造器:

// 创建一个FutureTask,一旦运行就执行给定的Callable
public FutureTask(Callable<V> callable) {
    if (callable == null)
        throw new NullPointerException();
    this.callable = callable;
    this.state = NEW;       // ensure visibility of callable
}
// 创建一个FutureTask,一旦运行就执行给定的Ru你那边了,并安排成功完成时get返回给定的结果
public FutureTask(Runnable runnable, V result) {
    this.callable = Executors.callable(runnable, result);
    this.state = NEW;       // ensure visibility of callable
}

其他常用的代码:

// get()获取call方法计算完成的返回值结果:
public V get() throws InterruptedException, ExecutionException {
    int s = state;
    if (s <= COMPLETING)
        s = awaitDone(false, 0L);
    return report(s);
}
// outcome就是返回值:
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);
}

未来的任务,如果运行过一次,那么下一次,就直接得到结果!

相关文章
|
1月前
|
Java 开发者
在 Java 中,一个类可以实现多个接口吗?
这是 Java 面向对象编程的一个重要特性,它提供了极大的灵活性和扩展性。
151 57
|
8天前
|
数据采集 JSON Java
利用Java获取京东SKU接口指南
本文介绍如何使用Java通过京东API获取商品SKU信息。首先,需注册京东开放平台账号并创建应用以获取AppKey和AppSecret。接着,查阅API文档了解调用方法。明确商品ID后,构建请求参数并通过HTTP客户端发送请求。最后,解析返回的JSON数据提取SKU信息。注意遵守API调用频率限制及数据保护法规。此方法适用于电商平台及其他数据获取场景。
|
13天前
|
安全 Java API
java如何请求接口然后终止某个线程
通过本文的介绍,您应该能够理解如何在Java中请求接口并根据返回结果终止某个线程。合理使用标志位或 `interrupt`方法可以确保线程的安全终止,而处理好网络请求中的各种异常情况,可以提高程序的稳定性和可靠性。
45 6
|
1月前
|
Java API
Java中内置的函数式接口
Java中内置的函数式接口
25 2
|
1月前
|
Java
在Java中,接口之间可以继承吗?
接口继承是一种重要的机制,它允许一个接口从另一个或多个接口继承方法和常量。
98 1
Java 基于Callable接口的线程实例
本文目录 1. 背景 2. 代码实现 3. 解析
129 0
|
3天前
|
Java
Java—多线程实现生产消费者
本文介绍了多线程实现生产消费者模式的三个版本。Version1包含四个类:`Producer`(生产者)、`Consumer`(消费者)、`Resource`(公共资源)和`TestMain`(测试类)。通过`synchronized`和`wait/notify`机制控制线程同步,但存在多个生产者或消费者时可能出现多次生产和消费的问题。 Version2将`if`改为`while`,解决了多次生产和消费的问题,但仍可能因`notify()`随机唤醒线程而导致死锁。因此,引入了`notifyAll()`来唤醒所有等待线程,但这会带来性能问题。
Java—多线程实现生产消费者
|
5天前
|
安全 Java Kotlin
Java多线程——synchronized、volatile 保障可见性
Java多线程中,`synchronized` 和 `volatile` 关键字用于保障可见性。`synchronized` 保证原子性、可见性和有序性,通过锁机制确保线程安全;`volatile` 仅保证可见性和有序性,不保证原子性。代码示例展示了如何使用 `synchronized` 和 `volatile` 解决主线程无法感知子线程修改共享变量的问题。总结:`volatile` 确保不同线程对共享变量操作的可见性,使一个线程修改后,其他线程能立即看到最新值。
|
5天前
|
消息中间件 缓存 安全
Java多线程是什么
Java多线程简介:本文介绍了Java中常见的线程池类型,包括`newCachedThreadPool`(适用于短期异步任务)、`newFixedThreadPool`(适用于固定数量的长期任务)、`newScheduledThreadPool`(支持定时和周期性任务)以及`newSingleThreadExecutor`(保证任务顺序执行)。同时,文章还讲解了Java中的锁机制,如`synchronized`关键字、CAS操作及其实现方式,并详细描述了可重入锁`ReentrantLock`和读写锁`ReadWriteLock`的工作原理与应用场景。
|
5天前
|
安全 Java 编译器
深入理解Java中synchronized三种使用方式:助您写出线程安全的代码
`synchronized` 是 Java 中的关键字,用于实现线程同步,确保多个线程互斥访问共享资源。它通过内置的监视器锁机制,防止多个线程同时执行被 `synchronized` 修饰的方法或代码块。`synchronized` 可以修饰非静态方法、静态方法和代码块,分别锁定实例对象、类对象或指定的对象。其底层原理基于 JVM 的指令和对象的监视器,JDK 1.6 后引入了偏向锁、轻量级锁等优化措施,提高了性能。
22 3