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的状态已经不是初始状态了。

这里是一些关键点:

  • FutureTask在执行后会进入完成状态。

  • 如果尝试再次执行一个已经完成的FutureTask,它不会重新执行。

  • 如果需要重新执行任务,您需要创建一个新的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());

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

  • 13
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值