Java多线程并发FutureTask使用详解

目录
  • 基本使用
  • 代码分析
    • 继承关系
    • Future
    • RunnableFuture
    • FutureTask
    • 状态
    • 属性
    • 内部类
    • 构造方法
    • 检索 FutureTask 状态
    • 取消操作
    • 计算结果
    • 立刻获取结果或异常
    • run 方法组

本文基于最新的 OpenJDK 代码,预计发行版本为 19 。

Java 的多线程机制本质上能够完成两件事情,异步计算和并发。并发问题通过解决线程安全的一系列 API 来解决;而异步计算,常见的使用是 Runnable 和 Callable 配合线程使用。

FutureTask 是基于 Runnable 实现的一个可取消的异步调用 API 。

基本使用

  • Future 代表了异步计算的结果,通过 ExecutorService 的 Future<?> submit(Runnable task) 方法,作为返回值使用:
interface ArchiveSearcher { String search(String target); }
class App {
		ExecutorService executor = ...;
    ArchiveSearcher searcher = ...;
    void showSearch(String target) throws InterruptedException {
       Callable<String> task = () -> searcher.search(target);
       Future<String> future = executor.submit(task); // 获取执行结果
       displayOtherThings(); // do other things while searching
       try {
         displayText(future.get()); // use future
       } catch (ExecutionException ex) { cleanup(); return; }
    }
}
  • FutureTask类是实现了Runnable的Future的实现,因此可以由Executor执行。例如,上述带有submit的构造可以替换为:
class App {
		ExecutorService executor = ...;
    ArchiveSearcher searcher = ...;
    void showSearch(String target) throws InterruptedException {
       Callable<String> task = () -> searcher.search(target);
       // 关键两行替换
       FutureTask<String> future = new FutureTask<>(task);
			 executor.execute(future);
       displayOtherThings(); // do other things while searching
       try {
         displayText(future.get()); // use future
       } catch (ExecutionException ex) { cleanup(); return; }
    }
}

代码分析

继承关系

Future

Future 表示异步计算的结果。定义了用于检查计算是否完成、等待计算完成以及检索计算结果的能力。只有在计算完成后,才能使用 get 方法检索结果,在必要时会阻塞线程直到 Future 计算完成。取消是由 cancel 方法执行的。还提供了其他方法来确定任务是正常完成还是被取消。一旦计算完成,就不能取消计算。如果为了可取消性而使用 Future ,但又不想提供一个可用的结果,你可以声明形式 Future<?> 并返回 null 作为任务的结果。

在介绍 Future 中定义的能力之前,先了解一下它的用来表示 Future 状态内部类,和状态检索方法:

public interface Future<V> {
    enum State {
       	// The task has not completed.
        RUNNING,
        // The task completed with a result. @see Future#resultNow()
        SUCCESS,
        //The task completed with an exception. @see Future#exceptionNow()
        FAILED,
        // The task was cancelled. @see #cancel(boolean)
        CANCELLED
    }

    default State state() {
        if (!isDone())		// 根据 isDone() 判断运行中
            return State.RUNNING;
        if (isCancelled()) // 根据 isCancelled() 判断已取消
            return State.CANCELLED;
        boolean interrupted = false;
        try {
            while (true) { // 死循环轮询
                try {
                    get();  // may throw InterruptedException when done
                    return State.SUCCESS;
                } catch (InterruptedException e) {
                    interrupted = true;
                } catch (ExecutionException e) {
                    return State.FAILED;
                }
            }
        } finally {
            if (interrupted) Thread.currentThread().interrupt();
        }
    }
}

Future 的状态检索的默认实现是根据 isDone()isCancelled() 和不断轮询 get() 方法获取到的返回值判断的。

get() 正常返回结果时, state() 返回 State.SUCCESS ; 当抛出 InterruptedException 时,最终会操作所在的线程执行尝试中断的方法;抛出其他异常时,则返回 State.FAILED

Future 中定义的其他方法包括:

package 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;
  	// 立刻返回结果
  	default V resultNow()
  	// 立刻抛出异常
  	default Throwable exceptionNow()
}

其中 resultNow()exceptionNow() 是带有默认实现的:

		default V resultNow() {
        if (!isDone())
            throw new IllegalStateException("Task has not completed");
        boolean interrupted = false;
        try {
            while (true) {
                try {
                    return get();
                } catch (InterruptedException e) {
                    interrupted = true;
                } catch (ExecutionException e) {
                    throw new IllegalStateException("Task completed with exception");
                } catch (CancellationException e) {
                    throw new IllegalStateException("Task was cancelled");
                }
            }
        } finally {
            if (interrupted) Thread.currentThread().interrupt();
        }
    }
  • Future 仍在运行中,直接抛出 IllegalStateException 。
  • 执行一个轮询,调用 get() 尝试返回计算结果,如果 get() 抛出异常,则根据异常抛出不同消息的 IllegalStateException 或执行中断线程的操作。
    default Throwable exceptionNow() {
        if (!isDone())
            throw new IllegalStateException("Task has not completed");
        if (isCancelled())
            throw new IllegalStateException("Task was cancelled");
        boolean interrupted = false;
        try {
            while (true) {
                try {
                    get();
                    throw new IllegalStateException("Task completed with a result");
                } catch (InterruptedException e) {
                    interrupted = true;
                } catch (ExecutionException e) {
                    return e.getCause();
                }
            }
        } finally {
            if (interrupted) Thread.currentThread().interrupt();
        }
    }
  • Future 仍在运行中,直接抛出 IllegalStateException 。
  • Future 检查是否已取消,如果取消了抛出 IllegalStateException 。
  • 执行轮询,调用 get() 方法,如果能够正常执行结束,也抛出 IllegalStateException ,消息是 "Task completed with a result" ;get() 若抛出 InterruptedException ,则执行线程中断操作;其他异常正常抛出。

这就是 Future 的全貌了。

RunnableFuture

RunnableFuture 接口同时实现了 Runnable 和 Future 接口 :

public interface RunnableFuture<V> extends Runnable, Future<V> {
    /**
     * Sets this Future to the result of its computation
     * unless it has been cancelled.
     * 除非已取消,否则将此Future设置为其计算的结果。
     */
    void run();
}

Runnable 接口是我们常用的用来实现线程操作的,可以说是十分熟悉也十分简单了。

这个接口代表了一个可以 Runnable 的 Future ,run 方法的成功执行代表着 Future 执行完成,并可以获取它的计算结果。

这个接口是 JDK 1.6 后续才有的。

FutureTask

FutureTask 是 RunnableFuture 的直接实现类,它代表了一个可取消的异步计算任务。根据我们对 Future 的分析和 Runnable 的熟悉,就可以理解它的作用了:可取消并可以检索运行状态的一个 Runnable ,配合线程使用可以中断线程执行。当任务没有执行完成时会造成阻塞。并且它还可以配合 Executor 使用。

状态

FutureTask 内部也定义了自己的状态:

public class FutureTask<V> implements RunnableFuture<V> {
		private volatile int state;
    private static final int NEW          = 0; // 新建
    private static final int COMPLETING   = 1; // 完成中
    private static final int NORMAL       = 2; // 正常完成
    private static final int EXCEPTIONAL  = 3; // 异常的
    private static final int CANCELLED    = 4; // 已取消
    private static final int INTERRUPTING = 5; // 中断中
    private static final int INTERRUPTED  = 6; // 已中断

		@Override
    public State state() {
        int s = state;
        while (s == COMPLETING) {
            // 等待过渡到 NORMAL 或 EXCEPTIONAL
            Thread.yield();
            s = state;
        }
        switch (s) {
            case NORMAL:
                return State.SUCCESS;
            case EXCEPTIONAL:
                return State.FAILED;
            case CANCELLED:
            case INTERRUPTING:
            case INTERRUPTED:
                return State.CANCELLED;
            default:
                return State.RUNNING;
        }
    }
}

FutureTask 的状态包括 7 种,最初为 NEW ,只有在 set、setException 和 cancel 方法中,运行状态才会转换为最终状态。在完成期间,状态可能为 COMPLETING (当结果正在设置时) 或 INTERRUPTING (仅当中断跑者以满足cancel(true) )的瞬态值。

可能存在的状态转换是:

NEW -> COMPLETING -> NORMAL // 正常完成
NEW -> COMPLETING -> EXCEPTIONAL // 抛出异常
NEW -> CANCELLED // 取消
NEW -> INTERRUPTING -> INTERRUPTED // 中断

属性

下面分析一下它的属性:

    /** 底层的调用;运行后为null */
    private Callable<V> callable;
    /** get()返回的结果或抛出的异常 */
    private Object outcome; // non-volatile, protected by state reads/writes
    /** The thread running the callable; CASed during run() */
    private volatile Thread runner;
    /** 等待线程的 Treiber 堆栈 */
    private volatile WaitNode waiters;

内部类

先看一看这个 WaitNode ,这是一个 FutureTask 的内部类:

    static final class WaitNode {
        volatile Thread thread;
        volatile WaitNode next;
        WaitNode() { thread = Thread.currentThread(); }
    }

一个链表结构,用来对等待线程进行排序。

构造方法

最后是方法的分析,首先是构造方法:

    // Creates a {@code FutureTask} that will, upon running, execute the given {@code Callable}.
    public FutureTask(Callable<V> callable) {
        if (callable == null)
            throw new NullPointerException();
        this.callable = callable;
        this.state = NEW;       // ensure visibility of callable
    }

    /**
     * Creates a {@code FutureTask} that will, upon running, execute the
     * given {@code Runnable}, and arrange that {@code get} will return the
     * given result on successful completion.
     * Runnable 成功是返回给定的结果 result
     */
    public FutureTask(Runnable runnable, V result) {
        this.callable = Executors.callable(runnable, result);
        this.state = NEW;       // ensure visibility of callable
    }

FutureTask 接收一个 Callable 或一个 Runnable 作为参数,Runnable 会封装一下都保存到属性 callable ,然后更新 FutureTask 的状态为 NEW

从 Future 接口中实现的方法逐个分析:

检索 FutureTask 状态

    public boolean isCancelled() {
        return state >= CANCELLED; // 大于等于 4, 已取消、中断中、已中断
    }

    public boolean isDone() {
        return state != NEW; // 不是 new 就代表执行结束了
    }

取消操作

    // mayInterruptIfRunning 表示最终的取消是通过中断还是通过取消。
		public boolean cancel(boolean mayInterruptIfRunning) {
        if (!(state == NEW && STATE.compareAndSet(this, NEW, mayInterruptIfRunning ? INTERRUPTING : CANCELLED)))  // 尝试设置 CANCELLED 或 INTERRUPTING
            return false;
        try {    // in case call to interrupt throws exception
            if (mayInterruptIfRunning) {
                try {
                    Thread t = runner;
                    if (t != null)
                        t.interrupt(); // 通过中断取消任务
                } finally { // final state
                    STATE.setRelease(this, INTERRUPTED); // 更新中断状态
                }
            }
        } finally {
            finishCompletion();
        }
        return true;
    }

这里的 finishCompletion() 的作用是通过 LockSupport 唤醒等待的全部线程并从等待列表中移除,然后调用done(),最后把 callable 置空。相当于取消成功后释放资源的操作。

    private void finishCompletion() {
        // assert state > COMPLETING;
        for (WaitNode q; (q = waiters) != null;) {
            if (WAITERS.weakCompareAndSet(this, q, null)) {
                for (;;) {
                    Thread t = q.thread;
                    if (t != null) {
                        q.thread = null;
                        LockSupport.unpark(t);
                    }
                    WaitNode next = q.next;
                    if (next == null)
                        break;
                    q.next = null; // unlink to help gc
                    q = next;
                }
                break;
            }
        }
        done();
        callable = null;        // to reduce footprint
    }

done() 是个空实现,供子类去自定义的。

protected void done() { }

计算结果

    public V get() throws InterruptedException, ExecutionException {
        int s = state;
        if (s <= COMPLETING)
            s = awaitDone(false, 0L); // 异步结果
        return report(s);
    }
    public V get(long timeout, TimeUnit unit)
        throws InterruptedException, ExecutionException, TimeoutException {
        if (unit == null)
            throw new NullPointerException();
        int s = state;
        if (s <= COMPLETING &&
            (s = awaitDone(true, unit.toNanos(timeout))) <= COMPLETING)
            throw new TimeoutException();
        return report(s);
    }

这里涉及两个方法:awaitDone 方法和 report 方法 。

awaitDone 方法:

    private int awaitDone(boolean timed, long nanos)
        throws InterruptedException {
        // The code below is very delicate, to achieve these goals:
        // - if nanos <= 0L, 及时返回,不需要 allocation 或 nanoTime
        // - if nanos == Long.MIN_VALUE, don't underflow
        // - if nanos == Long.MAX_VALUE, and nanoTime is non-monotonic
        //   and we suffer a spurious wakeup, we will do no worse than
        //   to park-spin for a while
        long startTime = 0L;    // Special value 0L means not yet parked
        WaitNode q = null;
        boolean queued = false;
        for (;;) {
            int s = state;
            if (s > COMPLETING) {  // COMPLETING = 1
                if (q != null)
                    q.thread = null;
                return s;
            }
            else if (s == COMPLETING) // 瞬时态,完成中
                // We may have already promised (via isDone) that we are done
                // so never return empty-handed or throw InterruptedException
                Thread.yield();
            else if (Thread.interrupted()) {
                removeWaiter(q); // 线程中断,移除等待的线程
                throw new InterruptedException();
            }
            else if (q == null) {
                if (timed && nanos <= 0L)
                    return s;
                q = new WaitNode();
            }
            else if (!queued)
                queued = WAITERS.weakCompareAndSet(this, q.next = waiters, q);
            else if (timed) { // 设置超时时间的情况
                final long parkNanos;
                if (startTime == 0L) { // first time
                    startTime = System.nanoTime();
                    if (startTime == 0L)
                        startTime = 1L;
                    parkNanos = nanos;
                } else {
                    long elapsed = System.nanoTime() - startTime;
                    if (elapsed >= nanos) {
                        removeWaiter(q);
                        return state;
                    }
                    parkNanos = nanos - elapsed;
                }
                // nanoTime may be slow; recheck before parking
                if (state < COMPLETING)
                    LockSupport.parkNanos(this, parkNanos);
            }
            else
                LockSupport.park(this);
        }
    }

通过 CAS 和 LockSupport 的挂起/唤醒操作配合,阻塞当前线程,异步地等待计算结果。

这里有个 removeWaiter 方法,内部就是遍历 waiters ,删除超时和中断的等待线程。

当异步逻辑执行完成后,调用 report 方法:

    // 为完成的任务返回结果或抛出异常
    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);
    }

这里用到了一个 outcome ,它是一个 Object 类型,作为返回结果,通过 set 方法可以对它进行设置:

    // 除非该 future 已被设置或取消,否则将该 future 的结果设置为给定值。
		// 该方法在成功完成计算后由 run 方法在内部调用。
		protected void set(V v) {
        if (STATE.compareAndSet(this, NEW, COMPLETING)) {
            outcome = v;
            STATE.setRelease(this, NORMAL); // final state
            finishCompletion();
        }
    }

立刻获取结果或异常

这两个方法都是通过 outcome 预设的返回值,返回预期的结果或异常。

    public V resultNow() {
        switch (state()) {    // Future.State
            case SUCCESS:
                @SuppressWarnings("unchecked")
                V result = (V) outcome;
                return result;
            case FAILED:
                throw new IllegalStateException("Task completed with exception");
            case CANCELLED:
                throw new IllegalStateException("Task was cancelled");
            default:
                throw new IllegalStateException("Task has not completed");
        }
    }

    @Override
    public Throwable exceptionNow() {
        switch (state()) {    // Future.State
            case SUCCESS:
                throw new IllegalStateException("Task completed with a result");
            case FAILED:
                Object x = outcome;
                return (Throwable) x;
            case CANCELLED:
                throw new IllegalStateException("Task was cancelled");
            default:
                throw new IllegalStateException("Task has not completed");
        }
    }

run 方法组

最后是实现了 Runnable 的 run 方法:

    public void run() {
      	// 保证 NEW 状态和 RUNNER 成功设置当前线程
        if (state != NEW ||
            !RUNNER.compareAndSet(this, null, Thread.currentThread()))
            return;
        try {
            Callable<V> c = callable; // 待执行的 Callable
            if (c != null && state == NEW) {
                V result;
                boolean ran;
                try {
                    result = c.call(); // 执行 Callable
                    ran = true;
                } catch (Throwable ex) {
                    result = null;
                    ran = false;
                    setException(ex);
                }
                if (ran)
                    set(result);
            }
        } finally {
            // 为了防止并发调用 run ,直到 state 确定之前, runner 必须是非空的
            runner = null;
            // 状态必须在 runner 置空后重新读取,以防止泄漏中断
            int s = state;
            if (s >= INTERRUPTING)
                handlePossibleCancellationInterrupt(s);
        }
    }

这里涉及两个方法,第一个是 setException(ex) :

    // 导致该future报告一个{@link ExecutionException},并将给定的可抛出对象作为其原因,除非该future已经被设置或取消。
    protected void setException(Throwable t) {
        if (STATE.compareAndSet(this, NEW, COMPLETING)) {
            outcome = t;
            STATE.setRelease(this, EXCEPTIONAL); // final state
            finishCompletion();
        }
    }

另一个是 handlePossibleCancellationInterrupt 方法:

    /**
     * 确保任何来自可能的 cancel(true) 的中断只在 run 或 runAndReset 时交付给任务。
     */
    private void handlePossibleCancellationInterrupt(int s) {
        // It is possible for our interrupter to stall before getting a
        // chance to interrupt us.  Let's spin-wait patiently.
        if (s == INTERRUPTING)
            while (state == INTERRUPTING)
                Thread.yield(); // wait out pending interrupt

        // assert state == INTERRUPTED;
        // 我们想清除可能从cancel(true)接收到的所有中断。
        // 然而,允许使用中断作为任务与其调用者通信的独立机制,并没有办法只清除取消中断。
        // Thread.interrupted();
    }

最后是 runAndReset 方法:

    protected boolean runAndReset() {
        if (state != NEW || !RUNNER.compareAndSet(this, null, Thread.currentThread()))
            return false;
        boolean ran = false; // flag 表示正常执行结束
        int s = state;
        try {
            Callable<V> c = callable;
            if (c != null && s == NEW) {
                try {
                    c.call(); // don't set result
                    ran = true;
                } catch (Throwable ex) {
                    setException(ex);
                }
            }
        } finally {
            // runner must be non-null until state is settled to
            // prevent concurrent calls to run()
            runner = null;
            // state must be re-read after nulling runner to prevent
            // leaked interrupts
            s = state; //
            if (s >= INTERRUPTING)
                handlePossibleCancellationInterrupt(s);
        }
        return ran && s == NEW; // 当正常执行结束,且 state 一开始就是 NEW 时,表示可以运行并重置。
    }

执行计算时不设置其结果,然后将该 future 重置为初始状态,如果计算遇到异常或被取消,则不这样做。这是为本质上执行多次的任务设计的。

run 和 runAndReset 都用到了一个 RUNNER , 最后就来揭秘一下这个东西:

    private static final VarHandle STATE;
    private static final VarHandle RUNNER;
    private static final VarHandle WAITERS;
    static {
        try {
            MethodHandles.Lookup l = MethodHandles.lookup();
            STATE = l.findVarHandle(FutureTask.class, "state", int.class);
            RUNNER = l.findVarHandle(FutureTask.class, "runner", Thread.class);
            WAITERS = l.findVarHandle(FutureTask.class, "waiters", WaitNode.class);
        } catch (ReflectiveOperationException e) {
            throw new ExceptionInInitializerError(e);
        }

        // Reduce the risk of rare disastrous classloading in first call to
        // LockSupport.park: https://bugs.openjdk.java.net/browse/JDK-8074773
        Class<?> ensureLoaded = LockSupport.class;
    }

MethodHandles.lookup()创建一个MethodHandles.Lookup对象,该对象可以创建所有访问权限的方法,包括publicprotectedprivatedefault

VarHandle 主要用于动态操作数组的元素或对象的成员变量VarHandle通过 MethodHandles 来获取实例,然后调用 VarHandle 的方法即可动态操作指定数组的元素或指定对象的成员变量。

到此这篇关于Java 多线程并发FutureTask的文章就介绍到这了,更多相关Java 多线程并发内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Java 多线程并发LockSupport

    目录 概览 源码分析 静态方法 Blocker unpark Unsafe 的 unpark 方法 park 不带 blocker 参数的分组 需要 blocker 参数的分组 park/unpark 和 Object 的 wait/notify 区别 概览 这部分内容来自于这个类的注释,简单翻译了下. LockSupport 类是用于创建锁和其他同步类的基本线程阻塞原语. 它的实现思想是给每个使用它的线程颁发一个许可,当许可是可用状态时(线程有许可),调用 park 方法会消耗一个许可,方法立

  • Java多线程并发编程和锁原理解析

    这篇文章主要介绍了Java多线程并发编程和锁原理解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 一.前言 最近项目遇到多线程并发的情景(并发抢单&恢复库存并行),代码在正常情况下运行没有什么问题,在高并发压测下会出现:库存超发/总库存与sku库存对不上等各种问题. 在运用了 限流/加锁等方案后,问题得到解决. 加锁方案见下文. 二.乐观锁 & 悲观锁 1.乐观锁 顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁

  • Java线程池FutureTask实现原理详解

    前言 线程池可以并发执行多个任务,有些时候,我们可能想要跟踪任务的执行结果,甚至在一定时间内,如果任务没有执行完成,我们可能还想要取消任务的执行,为了支持这一特性,ThreadPoolExecutor提供了 FutureTask 用于追踪任务的执行和取消.本篇介绍FutureTask的实现原理. 类视图 为了更好的理解FutureTask的实现原理,这里先提供几个重要接口和类的结构,如下图所示: RunnableAdapter ThreadPoolExecutor提供了submit接口用于提交任

  • Java多线程并发synchronized 关键字

    目录 基础 修饰普通方法 修饰静态方法 Synchronized 加锁原理 monitorenter monitorexit synchronized 修饰静态方法 优点.缺点及优化 其他说明 基础 Java 在虚拟机层面提供了 synchronized 关键字供开发者快速实现互斥同步的重量级锁来保障线程安全. synchronized 关键字可用于两种场景: 修饰方法. 持有一个对象,并执行一个代码块. 而根据加锁的对象不同,又分为两种情况: 对象锁 类对象锁 以下代码示例是 synchron

  • java编程多线程并发处理实例解析

    本文主要是通过一个银行用户取钱的实例,演示java编程多线程并发处理场景,具体如下. 从一个例子入手:实现一个银行账户取钱场景的实例代码. 第一个类:Account.java 账户类: package cn.edu.byr.test; public class Account { private String accountNo; private double balance; public Account(){ } public Account(String accountNo,double

  • Java多线程之FutureTask的介绍及使用

    一.FutureTask的理解 FutureTask属于java.util.concurrent 包:FutureTask表示可取消的异步计算.FutureTask类提供了一个Future的基本实现 ,具有启动和取消计算的方法,查询计算是否完整,并检索计算结果.结果只能在计算完成后才能检索; 如果计算尚未完成,则get方法将阻止. 一旦计算完成,则无法重新启动或取消计算(除非使用runAndReset()调用计算 ). 二.FutureTask类图 从上面的FutureTask类图中可以看出,F

  • Java中Future和FutureTask的示例详解及使用

    目录 一.Future 接口 二.FutureTask 三.使用 Callable 和 Future 四.小结(FutureTask核心原理) 总结 一.Future 接口 当 call()方法完成时,结果必须存储在主线程已知的对象中,以便主线程可以知道该线程返回的结果.为此,可以使用 Future 对象. 将 Future 视为保存结果的对象–它可能暂时不保存结果,但将来会保存(一旦Callable 返回).Future 基本上是主线程可以跟踪进度以及其他线程的结果的一种方式.要实现此接口,必

  • Java FutureTask类使用案例解析

    FutureTask一个可取消的异步计算,FutureTask 实现了Future的基本方法,提空 start cancel 操作,可以查询计算是否已经完成,并且可以获取计算的结果.结果只可以在计算完成之后获取,get方法会阻塞当计算没有完成的时候,一旦计算已经完成,那么计算就不能再次启动或是取消. 一个FutureTask 可以用来包装一个 Callable 或是一个runnable对象.因为FurtureTask实现了Runnable方法,所以一个 FutureTask可以提交(submit

  • Java多线程并发FutureTask使用详解

    目录 基本使用 代码分析 继承关系 Future RunnableFuture FutureTask 状态 属性 内部类 构造方法 检索 FutureTask 状态 取消操作 计算结果 立刻获取结果或异常 run 方法组 本文基于最新的 OpenJDK 代码,预计发行版本为 19 . Java 的多线程机制本质上能够完成两件事情,异步计算和并发.并发问题通过解决线程安全的一系列 API 来解决:而异步计算,常见的使用是 Runnable 和 Callable 配合线程使用. FutureTask

  • java多线程JUC常用辅助类详解

    1.countDownLatch 减法计数器:实现调用几次线程后,在触发另一个任务 简单代码实现: 举例说明:就像五个人在同一房间里,有一个看门的大爷,当五个人都出去后,他才能锁门,也就是说 执行5次出门这个动作的线程后,才出发了锁门的这个动作 import java.util.concurrent.CountDownLatch; /** * @program: juc * @description * @author: 不会编程的派大星 * @create: 2021-04-24 16:55

  • Java多线程编程综合案例详解

    目录 Java多线程综合案例 数字加减 生产电脑 竞争抢答 Java多线程综合案例 数字加减 设计4个线程对象,两个线程执行减操作,两个线程执行加操作 public class ThreadDemo{ public static void main(String[] args) throws Exception { Resource res=new Resource(); AddThread at=new AddThread(res); SubThread st=new SubThread(re

  • Java多线程解决龟兔赛跑问题详解

    目录 多线程4(龟兔赛跑-休眠线程) 1.题目 2.解题思路 3.代码详解 多线程4(龟兔赛跑-休眠线程) 1.题目 在龟兔赛跑中,领先的兔子因为通宵写博客,中途太累睡着了,跑输了乌龟.这个故事说明了兔子是爱学习的同学.咳咳,通宵是不可取的,大家别学. 实现:使用线程休眠模拟龟兔赛跑比赛 2.解题思路 创建一个类:RaceFrame,继承了JFrame.用来界面显示两个文本区域,用来输出乌龟和兔子的比赛记录,比赛开始按钮用来开始比赛. 编写内部类:Rabbit,该类实现了Runnable接口,在

  • java ThreadPoolExecutor 并发调用实例详解

    java ThreadPoolExecutor 并发调用实例详解 概述 通常为了提供任务的处理速度,会使用一些并发模型,ThreadPoolExecutor中的invokeAll便是一种. 代码 package test.current; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.concurrent.Callable; import java.util

  • 基于多线程并发的常见问题(详解)

    一 概述 1.volatile 保证共享数据一旦被修改就会立即同步到共享内存(堆或者方法区)中. 2.线程访问堆中数据的过程 线程在栈中建立一个数据的副本,修改完毕后将数据同步到堆中. 3.指令重排 为了提高执行效率,CPU会将没有依赖关系的指令重新排序.如果希望控制重新排序,可以使用volatile修饰一个变量,包含该变量的指令前后的指令各自独立排序,前后指令不能交叉排序. 二 常见问题及应对 1.原子性问题 所谓原子性,指的是一个操作不可中断,即在多线程并发的环境下,一个操作一旦开始,就会在

  • Java多线程用法的实例详解

    Java多线程用法的实例详解 前言: 最全面的java多线程用法解析,如果你对Java的多线程机制并没有深入的研究,那么本文可以帮助你更透彻地理解Java多线程的原理以及使用方法. 1.创建线程 在Java中创建线程有两种方法:使用Thread类和使用Runnable接口.在使用Runnable接口时需要建立一个Thread实例.因此,无论是通过Thread类还是Runnable接口建立线程,都必须建立Thread类或它的子类的实例.Thread构造函数: public Thread( ); p

  • Java多线程通信实现方式详解

    这篇文章主要介绍了Java多线程通信实现方式详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 线程通信的方式: 1.共享变量 线程间通信可以通过发送信号,发送信号的一个简单方式是在共享对象的变量里设置信号值.线程A在一个同步块里设置boolean型成员变量hasDataToProcess为true,线程B也在同步代码块里读取hasDataToProcess这个成员变量.这个简单的例子使用了一个持有信号的对象,并提供了set和get方法. pu

  • Java多线程 线程状态原理详解

    这篇文章主要介绍了Java多线程 线程状态原理详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 java.lang.Thread.State枚举定义了6种线程状态. NEW: 尚未启动(start)的线程的线程状态 RUNNABLE: 运行状态,但线程可能正在JVM中执行,也可能在等待CPU调度 BLOCKED: 线程阻塞,等待监视器锁以进入同步代码块/方法 WAITING: 等待状态.使用以下不带超时的方式时会进入:Object.wait.

  • java ReentrantLock并发锁使用详解

    目录 一.ReentrantLock是什么 1-1.ReentrantLock和synchronized区别 1-2.ReentrantLock的使用 1-2-1.ReentrantLock同步执行,类似synchronized 1-2-2.可重入锁 1-2-3.锁中断 1-2-4.获得锁超时失败 1-2-5.公平锁 一.ReentrantLock是什么 ReentrantLock是一种基于AQS框架的应用实现,是JDK中的一种线程并发访问的同步手段,它的功能类似于synchronized是一种

随机推荐