手写一个callable创建线程,来了解下原理

1.先模拟源码的Callable创建自己的MyCallable

package com.example.test.demo.thread.callable;

/**
 * @author 王健宇
 * @title: MyCallable
 * @description
 * @date 2021/7/9 19:12
 */
public interface MyCallable<T> {
    T call();
}

2.创建自己的FutureTask

package com.example.test.demo.thread.callable;

/**
 * 因为要放在Thread中执行,所以要实现Runnable
 * @author 王健宇
 * @title: MyFutrueTask
 * @description
 * @date 2021/7/9 19:13
 */
public class MyFutureTask<T> implements Runnable{

    final Object object = new Object();

    private T result;

    private MyCallable<T> callable;

    public MyFutureTask(MyCallable<T> callable) {
        this.callable = callable;
    }

    @Override
    public void run() {
        result = callable.call();
        // 线程执行完,换新get()方法中等待的线程
        // wait要放在synchronized
        synchronized (object) {
            object.notify();
        }
    }

    /**
     * 获取多线程返回值
     * @return 返回多线程执行结果
     */
    public T get () throws InterruptedException {
        // 必须等线程执行完才能返回
        // wait要放在synchronized
        synchronized (object) {
            object.wait();
            return result;
        }
    }
}

3.最后测试

package com.example.test.demo.thread.callable;

import com.example.test.pojo.User;

import java.util.Date;

/**
 * @author 王健宇
 * @title: MyCallableDemo
 * @description
 * @date 2021/7/9 19:14
 */
public class MyCallableDemo {
    public static void main(String[] args) throws InterruptedException {
        // 1. 创建callable
        MyCallable<User> callable = new MyCallable<User>() {
            @Override
            public User call() {
                // 模拟执行耗时 3秒
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                return new User("用户" + new Date().getTime(), "29");
            }
        };
        // 2.创建futureTask
        MyFutureTask<User> future = new MyFutureTask<>(callable);

        // 3.放到线程中执行
        new Thread(future).start();
        // 4.获取返回结果
        User user = future.get();
        // 5.打印
        System.out.println(user);
    }
}

4.最后,这里是用wait和notify模拟的,还可以使用

LockSupport.park();
LockSupport.unpark();

来实现

### 回答1: 线程的本质就是一个可执行的任务或程序,它可以在一个独立的执行流中运行,以便它可以并行执行多个任务。Callable可以用来创建线程,只要将它以Callable对象的形式传递给ExecutorService然后调用它的submit()方法来创建线程。 ### 回答2: Callable 创建线程的本质是通过实现 Callable 接口来定义一个可以返回结果的任务,并通过 Future 接口来获取任务的执行结果。 Callable 接口是一个泛型接口,其中的泛型类型指定了返回结果的类型。该接口只有一个 call() 方法,用于执行任务逻辑并返回结果。在创建线程时,可以将实现了 Callable 接口的任务作为参数传递给 Thread 类的构造方法。在线程运行时,会执行任务的 call() 方法。 与 Runnable 接口不同,Callable 接口的 call() 方法可以返回一个结果对象,而 Runnable 接口的 run() 方法是没有返回值的。为了获取 Callable 任务的执行结果,可以通过 Future 接口来管理任务的执行状态和返回结果。Future 接口有几个重要的方法,如 get() 方法用于获取执行结果,isDone() 方法用于判断任务是否完成等。 CallableFuture 的组合实现了线程的异步执行和结果获取。可以通过线程池来管理和调度 Callable 任务,使得多个 Callable 任务可以并发执行,并且可以根据需要获取各个任务的执行结果。 总之,创建线程的本质是通过实现 Callable 接口来定义任务,使用线程池或者手动创建线程来执行任务,并通过 Future 接口来获取执行结果。这种方式可以更灵活地控制线程的执行,并且可以获取任务的执行结果。 ### 回答3: Callable 创建线程的本质是使用 Callable 接口来定义一个具有返回值的任务,并将其提交给线程池进行执行。Callable 接口是一个泛型接口,通过实现其中的 call() 方法来定义任务的执行逻辑,并可以通过返回值来获取任务的执行结果。 与 Runnable 接口不同,Callable 接口的 call() 方法可以抛出异常并返回一个结果。可以通过调用 ExecutorService 的 submit() 方法将 Callable 对象提交给线程池,线程池会将其封装为一个 Future 对象。通过 Future 对象可以在任务执行完毕后获取任务的执行结果,可以使用 get() 方法阻塞地获取结果,也可以使用 isDone() 方法判断任务是否执行完毕。 Callable 接口的创建线程本质上是将任务的执行逻辑抽象为一个对象,然后将该对象提交给线程池进行执行,线程池会自动分配线程去执行任务,通过 Future 对象来获取任务执行结果。这种方式可以方便地进行任务的分发和管理,提高线程的复用性和执行效率。 总之,Callable 创建线程的本质是将任务逻辑封装为一个 Callable 对象,并通过线程池来管理任务的执行,通过 Future 对象来获取任务的执行结果。相比于直接创建线程,使用 Callable 更加灵活,可以方便地实现任务的控制和结果的获取。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值