• java多线程--Callable、Future


    Java 实现多线程的二种方式:

    方式一:继承Thread类
    方式二:实现Runnable接口

    示例代码如下:

      // 方式一:继承Thread类
            Thread thread01 = new Thread() {
                @Override
                public void run() {
                    System.out.println("线程二:hello");
                }
            };
            thread01.start();
    
            // 方式二:实现Runnable接口
            Thread thread02 = new Thread(() -> System.out.println("线程三:hello"));
            thread02.start();

    这2种方式都有一个缺陷就是:在执行完任务之后无法获取执行结果。

    自从Java 1.5开始,就提供了Callable和Future,通过它们可以在任务执行完毕之后得到任务执行结果。

    下面就来了解下Callable与Runnable

    Callable 与 Runnable

    Runnable接口,来自java.lang.Runnable,只声明了run()方法

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

    由于run()方法返回值为void类型,所以在执行完任务之后无法返回任何结果。

    Callable接口,来自java.util.concurrent.Callable<V>,也只声明了一个call()方法

    @FunctionalInterface
    public interface Callable<V> {
        V call() throws Exception;
    }
    可以看到,这是一个泛型接口,call()函数返回的类型就是传递进来的V类型。
    那么怎么使用Callable呢?一般情况下是配合ExecutorService来使用的
    <T> Future<T> submit(Callable<T> task);
    <T> Future<T> submit(Runnable task, T result);
    Future<?> submit(Runnable task);

    接下来了解下Future

    Future

    Future就是对于具体的Runnable或者Callable任务的执行结果进行取消、查询是否完成、获取结果。必要时可以通过get方法获取执行结果,该方法会阻塞直到任务返回结果。

    Future类位于java.util.concurrent包下,它是一个接口:

    public interface Future<V> {
    
        boolean cancel(boolean mayInterruptIfRunning);
    
        boolean isCancelled();
    
        boolean isDone();
    
        V get() throws InterruptedException, ExecutionException;
    
        V get(long timeout, TimeUnit unit)
            throws InterruptedException, ExecutionException, TimeoutException;
    }

           boolean cancel(boolean mayInterruptRunning):试图取消该Future关联的Callable任务。

            V get():返回Callable里call()方法的返回值。该方法会导致程序阻塞,必须等到子线程结束时才能得到返回值。

            V get(long timeout,TimeUnit unit):返回Callable里call()方法的返回值。该方法最多让程序等待timeout和unit指定的时间,到达指定时间后还没有得到返回值,将会抛出TimeoutException异常。

            boolean isCancelled():如果Callable任务在正常完成前被取消,则返回true。

            boolean isDone():如果Callable任务已经完成,则返回true。

    也就是说Future提供了三种功能:

    1)判断任务是否完成;

    2)能够中断任务;

    3)能够获取任务执行结果。

    因为Future只是一个接口,所以是无法直接用来创建对象使用的,因此就有了下面的FutureTask

    FutureTask类实现了RunnableFuture接口。
    RunnableFuture继承了Runnable接口和Future接口,而FutureTask实现了RunnableFuture接口。所以它既可以作为Runnable被线程执行,又可以作为Future得到Callable的返回值。

    FutureTask提供了2个构造器:

    public FutureTask(Callable<V> callable) {}
    
    public FutureTask(Runnable runnable, V result) {}

    事实上,FutureTask是Future接口的一个唯一实现类。

    示例:

    了解了这些之后,下面是两个Callable的示例

    示例一:Thread.start()启动线程

    public static void main(String[] args) {
    
            // 获取线程的返回值
            AtomicInteger atomicInteger = new AtomicInteger(0);
    
            FutureTask futureTask = new FutureTask(() -> {
                atomicInteger.set(atomicInteger.get() + 1);
                return atomicInteger.get();
            });
    
            Thread thread = new Thread(futureTask);
            thread.start();
            try {
                System.out.println(
                        futureTask.get()
                );  // 1
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
        }

    示例二:通过ExecutorService执行线程

    public static void main(String[] args) {
    
            // 通过ExecutorService执行线程
            AtomicInteger atomicInteger = new AtomicInteger();
    
            ExecutorService executorService = Executors.newSingleThreadExecutor();
            Future submit = executorService.submit(() -> {
                atomicInteger.set(atomicInteger.get() + 1);
                return atomicInteger.get();
            });
            try {
                System.out.println(
                        submit.get()
                );
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
        }




  • 相关阅读:
    c# 使用Selenium模拟登录和操作数据的学习记录【续】
    c# 使用Selenium模拟登录和操作数据的学习记录
    使用bat一键安装mysql
    使用c#程序 添加iis网站目录的用户权限
    NOIp游记
    线规集合
    背包规划集合
    阴间扫描线
    11.30数学集合
    高精度运算
  • 原文地址:https://www.cnblogs.com/zouhong/p/13216564.html
Copyright © 2020-2023  润新知