java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > Java Thread , Future , Callable , FutureTask

Java多线程Thread , Future , Callable , FutureTask的使用

作者:perfecto1

本文主要介绍了Java多线程Thread , Future , Callable , FutureTask的使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

 Thread创建一个线程

在想要使用多线程的技术来进行相应的操作的时候: 可以含有以下的方向来进行设计思考! 在创建一个线程的时候通常是创建一个Thread的。 但是这个Thread,是含有多种方式来进行创建操作的。 例如: 直接使用空参数的构造器进行创建操作:

        System.out.println("start:" + System.currentTimeMillis());
        Thread thread = new Thread();
        thread.start();
        System.out.println("end:" + System.currentTimeMillis());

这样执行是没有什么效果的。这种情况就是你启动了一个线程,但是这个线程是没有任何事情要干的。

时间是过的飞起的。

但是还有一种方法也是可以进行线程的启动操作的。

使用含有参数方法的构造器进行创建线程:

System.out.println(Thread.currentThread() + "----start:" + System.currentTimeMillis());
Thread thread = new Thread(new Runnable() {
    @Override
    public void run() {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("我正在执行一个任务,不要打扰我!");
        System.out.println(Thread.currentThread());
    }
});
thread.start();
System.out.println(Thread.currentThread() + "----end:" + System.currentTimeMillis());

这种是开启一个线程让其来进行线程任务的执行操作的。

但是你有没有发现,这种方式有一点缺点的。

这个开启的线程是相当于我要让其进行一些子任务的执行操作的。

Thread进行异步处理

类似于我是老师,我想让学习委员去办公室帮我拿一些书来的。此时学习委员已经出发了,但是我想起来我好像是带了书的。我想要让学习委员不要去办公室拿书了。

若我直接采用这种方式来来进行执行操作的话,是无法满足我的需求的。只要是我叫他去拿书了,她就会喊不回来的。

那是否能对这种方式进行相应的改造操作呢???

java的开发者是给了我们一种实现的方式的。

使用Future的接口满足需求。

相应的解释:

A Future 表示异步计算的结果。提供了用于检查计算是否完成、等待计算完成以及检索计算结果的方法。只有在计算完成后才能使用方法 get 检索结果,必要时会阻止,直到它准备就绪。取消是通过该 cancel 方法执行的。提供了其他方法来确定任务是正常完成还是已取消。计算完成后,无法取消计算。如果为了可取消性而使用 a Future ,但不提供可用的结果,则可以声明表单 Future<?> 的类型,并作为基础任务的结果返回 null 。

public interface Future<V> {
​
    /**
     * Attempts to cancel execution of this task.  This attempt will
     * fail if the task has already completed, has already been cancelled,
     * or could not be cancelled for some other reason. If successful,
     * and this task has not started when {@code cancel} is called,
     * this task should never run.  If the task has already started,
     * then the {@code mayInterruptIfRunning} parameter determines
     * whether the thread executing this task should be interrupted in
     * an attempt to stop the task.
     *
     * <p>After this method returns, subsequent calls to {@link #isDone} will
     * always return {@code true}.  Subsequent calls to {@link #isCancelled}
     * will always return {@code true} if this method returned {@code true}.
     *
     * @param mayInterruptIfRunning {@code true} if the thread executing this
     * task should be interrupted; otherwise, in-progress tasks are allowed
     * to complete
     * @return {@code false} if the task could not be cancelled,
     * typically because it has already completed normally;
     * {@code true} otherwise
     */
    boolean cancel(boolean mayInterruptIfRunning);
​
    /**
     * Returns {@code true} if this task was cancelled before it completed
     * normally.
     *
     * @return {@code true} if this task was cancelled before it completed
     */
    boolean isCancelled();
​
    /**
     * Returns {@code true} if this task completed.
     *
     * Completion may be due to normal termination, an exception, or
     * cancellation -- in all of these cases, this method will return
     * {@code true}.
     *
     * @return {@code true} if this task completed
     */
    boolean isDone();
​
    /**
     * Waits if necessary for the computation to complete, and then
     * retrieves its result.
     *
     * @return the computed result
     * @throws CancellationException if the computation was cancelled
     * @throws ExecutionException if the computation threw an
     * exception
     * @throws InterruptedException if the current thread was interrupted
     * while waiting
     */
    V get() throws InterruptedException, ExecutionException;
​
    /**
     * Waits if necessary for at most the given time for the computation
     * to complete, and then retrieves its result, if available.
     *
     * @param timeout the maximum time to wait
     * @param unit the time unit of the timeout argument
     * @return the computed result
     * @throws CancellationException if the computation was cancelled
     * @throws ExecutionException if the computation threw an
     * exception
     * @throws InterruptedException if the current thread was interrupted
     * while waiting
     * @throws TimeoutException if the wait timed out
     */
    V get(long timeout, TimeUnit unit)
        throws InterruptedException, ExecutionException, TimeoutException;
}

通过这个接口就可以实现相对应的功能操作了。

给予了一个接口想要将其进行实现操作就得要相关的实现类。

登场的就是FutureTask的类进行操作的。

public FutureTask(Runnable runnable, V result) {
    this.callable = Executors.callable(runnable, result);
    this.state = NEW;       // ensure visibility of callable
}

执行一下相关的代码:

 FutureTask<String> stringFutureTask = new FutureTask<String>(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("我正在执行一个任务,不要打扰我!");
                System.out.println(Thread.currentThread());
            }
        } , null);
​
        Thread futureThread = new Thread(stringFutureTask);
        futureThread.start();
//      是可以满足对一个进行任务的取消工作的
//        stringFutureTask.cancel(true);
        System.out.println(stringFutureTask.isCancelled());
​
​
        Thread futureThread1 = new Thread(stringFutureTask);
        futureThread1.start();

第二个 futureThread1 是不会执行的。

解释原因:

在Java中,FutureTask只能执行一次。当您尝试第二次执行相同的FutureTask实例时,它不会执行任何操作。这是因为FutureTask的状态在第一次执行后会改变,它不会重新开始。如果第一个线程(futureThread)已经开始执行stringFutureTask,那么第二个线程(futureThread1)尝试开始相同的stringFutureTask时,将不会有任何效果,因为FutureTask的状态已经不是初始状态了。

这里是一些关键点:

上面相关的例子,已经将一个老师叫学习委员去办公室拿书的例子叫停了。也就是说现在是实现了异步处理的操作。

带有参数的返回线程处理

我现在还有一个需求,是干嘛的呢???我不是喊学习委员去办公室拿书了吗??我想要那个他拿到的书给我手上。这个功能是怎么实现的呢?

也就是含有返回值的相关的例子!!!

JUC给了一个方法,是可以直接将一个Callable的接口传过来的

public FutureTask(Callable<V> callable) {
    if (callable == null)
        throw new NullPointerException();
    this.callable = callable;
    this.state = NEW;       // ensure visibility of callable
}

使用这个接口作为参数传给的FutureTask进行任务的初始化操作。

我们知道Callable接口是有返回值的。那么就可以类似于得到相应的那一本书了!!!

操作实现:

    FutureTask<String> stringFutureTask = new FutureTask<String>(new Callable<String>() {
        @Override
        public String call() throws Exception {
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("我正在执行一个任务,不要打扰我!");
            return "老师,我拿到书了";
        }
    });
​
    Thread thread = new Thread(stringFutureTask);
    thread.start();
    System.out.println(stringFutureTask.get());

将得到的东西进行返回操作。这样的话就可以实现三种基本的功能操作了。

到此这篇关于Java多线程Thread , Future , Callable , FutureTask的使用的文章就介绍到这了,更多相关Java Thread , Future , Callable , FutureTask内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文