Java多线程: 线程的创建和启动

本文介绍了Java中创建线程的三种方式:继承Thread类、实现Runnable接口和使用Callable与Future。重点讲解了Callable接口相较于Runnable接口的优势,包括能够返回执行结果及声明抛出异常。并比较了不同创建方式的特点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Java中线程的创建方式有3种.下面依次介绍:

一.继承Thread类创建线程类

二.实现Runable接口创建线程类

三.使用Callable和Future创建线程类

从Java5开始,Java提供了Callable接口,该接口怎么看都像是Runable接口的增强版,Callable接口提供了一个call()方法可以作为线程执行体,但call()方法比run()方法功能更强大。

(1) call( ) 方法可以有返回值;

(2) call( )方法可以声明抛出异常。

步骤如下:
(1)创建Callable接口的实现类,并实现call()方法,该call()方法将作为线程执行体,并且有返回值。
(2)创建Callable实现类的实例,使用FutureTask类来包装Callable对象,该FutureTask对象封装了该Callable对象的call()方法的返回值。
(3)使用FutureTask对象作为Thread对象的target创建并开启新线程。
(4)调用FutureTask对象的get()方法来获得子线程执行结束后的返回值,调用 get()方法会阻塞线程。

代码如下:

      FutureTask<Integer> task = new FutureTask<>(new Callable<Integer>() {
            @Override
            public Integer call() throws Exception {
                int i = 0;
                for (; i < 200; i++) {
                    System.out.println(Thread.currentThread().getName() + "的循环变量i的值:" + i);
                }
                return i;
            }
        });

        for (int i = 0; i < 100; i++) {
            System.out.println(Thread.currentThread().getName()
                    + " 的循环变量i的值:" + i);
            if (i == 20) {
                // 实质还是以Callable对象来创建、并启动线程
                new Thread(task, "有返回值的线程").start();
            }
        }

        try {
            // 获取线程返回值
            System.out.println("子线程的返回值:" + task.get());
        } catch (Exception ex) {
            ex.printStackTrace();
        }

第23行代码对应的打印结果为 子线程的返回值:200。 这是因为第5-7行for循环执行完之后,才进入第8行代码。

上面程序中可以发现, 实现Callable接口与实现Runnable接口并没有太大的差别,只是Callable的call()方法允许声明抛出异常,而且允许带返回值。

上面程序中的第1-10行代码是以Callable对象来启动线程的关键代码。程序先创建一个Callable对象,然后将该实例包装成一个 FutureTask对象。主线程中当循环变量i等于20时,程序启动以FutureTask对象为target 的线程。程序最后调用FutureTask 对象的get()方法来返回call0方法的返回值一该方法将 导致主线程被阻塞,直到call()方法结束并返回为止。

运行上面程序,将看到主线程和call()方法所代表的线程交替执行的情形,程序最后还会输出call()方法的返回值。.

四. 创建线程的三种方式对比

通过继承Thread类或实现Runnable、Callable 接口都可以实现多线程,不过实现Runnable接口与实现Callable接口的方式基本相同,只是Callable接口里定义的方法有返回值,可以声明抛出异常而已。因此可以将实现Runnable接口和实现Callable 接口归为一种方式。 这种方式与继承Thread方式之间的主要差别如下。

采用实现Runnable、Callable 接口的方式创建多线程的优缺点:

  • 线程类只是实现了Runnable接口或Callable接口,还可以继承其他类。

  • 在这种方式下,多个线程可以共享同一个target 对象,所以非常适合多个相同线程来处理同一份资源的情况,从而可以将CPU、代码和数据分开,形成清晰的模型,较好地体现了面向对象的思想。

  • 劣势是,编程稍稍复杂,如果需要访问当前线程,则必须使用Thread.currentThread()方法。

采用继承Thread类的方式创建多线程的优缺点:

  • 劣势是,因为线程类已经继承了Thread 类,所以不能再继承其他父类。

  • 优势是,编写简单,如果需要访问当前线程,则无须使用Thread.currentThread()方法, 直接使用this即可获得当前线程。

    鉴于上面分析,因此一般推荐采用实现Runnable接口、Callable 接口的方式来创建多线程。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值