前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >详解多线程启动涉及的知识点

详解多线程启动涉及的知识点

作者头像
BUG弄潮儿
发布2022-06-30 16:55:07
1760
发布2022-06-30 16:55:07
举报
文章被收录于专栏:JAVA乐园JAVA乐园

Thread类

如果一个类继承Thread,则不适合资源共享。但是如果实现了Runable接口的话,则很容易地实现资源共享。实现Runnable接口比继承Thread类所具有的优势:

  • 适合多个相同的程序代码的线程去处理同一个资源
  • 可以避免java中的单继承的限制
  • 增加程序的健壮性,代码可以被多个线程共享,代码和数据独立
代码语言:javascript
复制
//继承 Thread
Thread1 mTh1=new Thread1("A");
Thread1 mTh2=new Thread1("B");
mTh1.start();
mTh2.start();

Runnable接口

代码语言:javascript
复制
// 先看一下java.lang.Runnable,它是一个接口,在它里面只声明了一个run()方法:
// 由于run()方法返回值为void类型,所以在执行完任务之后无法返回任何结果。
public interface Runnable {
    public abstract void run();
}

//实现Runnable接口
Thread2 mTh = new Thread2();
new Thread(mTh, "C").start();//同一个mTh,但是在Thread中就不可以,如果用同一个实例化对象mt,就会出现异常   
new Thread(mTh, "D").start();
new Thread(mTh, "E").start();

这两种方式都有一个缺陷就是:在执行完任务之后无法获取执行结果。如果需要获取执行结果,就必须通过共享变量或者使用线程通信的方式来达到效果,这样使用起来就比较麻烦。

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

Callable接口

Callable接口位于java.util.concurrent包下,在它里面也只声明了一个方法,只不过这个方法叫做call()。

代码语言:javascript
复制
public interface Callable<V> {
    V call() throws Exception;
}

可以看到,这是一个泛型接口,call()函数返回的类型就是传递进来的V类型。Callable接口可以看作是Runnable接口的补充,call方法带有返回值,并且可以抛出异常。

FutureTask类

如何获取Callable的返回结果呢?一般是通过FutureTask这个中间媒介来实现的。整体的流程是这样的:

  • 把Callable实例当作参数,生成一个FutureTask的对象
  • 然后把这个对象当作一个Runnable,作为参数另起线程。

由于FutureTask实现了Runnable,因此它既可以通过Thread包装来直接执行,也可以提交给ExecuteService来执行。下面以Thread包装线程方式启动来说明一下。

代码语言:javascript
复制
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;

public class Demo {
    public static void main(String[] args) throws Exception {
        Callable<Integer> call = new Callable<Integer>() {
            public Integer call() throws Exception {
                System.out.println("计算线程正在计算结果...");
                Thread.sleep(3000);
                return 1;
            }
        };

        FutureTask<Integer> task = new FutureTask<>(call);
        Thread thread = new Thread(task);
        thread.start();
        System.out.println("main线程干点别的...");
        Integer result = task.get();
        System.out.println("从计算线程拿到的结果为:" + result);
    }
}

Future接口

FutureTask继承体系中的核心接口是Future。

Future的核心思想是:一个方法,计算过程可能非常耗时,等待方法返回,显然不明智。可以在调用方法的时候,立马返回一个Future,可以通过Future这个数据结构去控制方法f的计算过程。这里的控制包括:

代码语言:javascript
复制
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;
}

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

  • 判断任务是否完成;
  • 能够中断任务;
  • 能够获取任务执行结果。

实现Runnable接口和Callable接口的区别

如果想让线程池执行任务的话需要实现的Runnable接口或Callable接口。

Runnable接口或Callable接口实现类都可以被ThreadPoolExecutor或ScheduledThreadPoolExecutor执行。两者的区别在于 Runnable 接口不会返回结果但是 Callable 接口可以返回结果。

备注:工具类 Executors 可以实现 Runnable 对象和 Callable 对象之间的相互转换。 Executors.callable(Runnable task)也就是说Future提供了三种功能:

  • 判断任务是否完成;
  • 能够中断任务;
  • 能够获取任务执行结果。Executors.callable(Runnable task,Object resule )。
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2022-06-14,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 BUG弄潮儿 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Thread类
  • Runnable接口
  • Callable接口
  • FutureTask类
  • Future接口
  • 实现Runnable接口和Callable接口的区别
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档