Java基础:线程的三种创建方式

一、继承Thread类

  1. 定义一个类继承线程类Thread
  2. 重写run()方法
  3. 创建线程对象
  4. 调用线程对象的start()方法创建线程

Thread类的常用API

  • setName(String name):给线程取名字
  • getName():获取线程的名字
  • public static Thread currentThread():获取当前线程对象,这个代码在哪个线程中就获取哪个线程对象
  • public static void sleep(long time):让当前线程休眠多少毫秒再继续执行

优点:

  • 编码简单

缺点:

  • 线程类已经继承Thread就无法继承其他类了,功能无法通过继承拓展(单继承的局限性)

二、实现Runable接口

  1. 定义一个线程任务类实现Runable接口
  2. 重写run()方法
  3. 创建线程任务对象
  4. 把线程任务对象包装成线程对象
  5. 调用线程对象的start()方法启动线程
java 复制代码
class MyRunable implements Runnable{

    @Override
    public void run() {
        System.out.println("hello runable");
    }
}
java 复制代码
public static void main(String[] args) {
    MyRunable target = new MyRunable();
    Thread t = new Thread(target);
    t.start();
}

优点:

  • 避免了Java单继承的局限性
  • 同一个任务对象可以被包装成多个线程对象
  • 适合多个线程去共享同一个资源
  • 实现解耦,线程任务代码可以被多个线程共享,线程任务代码和线程独立
  • 线程池只能放入实现Runable和Callable接口的线程任务,不能直接放入继承Thread类的线程对象

缺点

  • 编码复杂(其实还好啦)

匿名内部类的写法:

java 复制代码
Runnable target = new Runnable() {
    @Override
    public void run() {
        System.out.println("匿名内部类写法");
    }
};
Thread t = new Thread(target);
t.start();

//简化
new Thread(new Runnable() {
    @Override
    public void run() {
        System.out.println("匿名内部类写法");
    }
}).start();

//再简化
new Thread(() -> System.out.println("匿名内部类写法")).start();

三、实现Callable接口

  1. 定义一个线程任务类实现Callable接口,申明线程执行的结果类型
  2. 重写线程任务类的call方法,这个方法可以直接返回执行结果
  3. 创建一个Callable的线程任务对象
  4. 把线程任务对象包装成一个未来任务对象
  5. 把未来任务对象包装成线程对象
  6. 调用start()方法启动线程
java 复制代码
//1.定义一个线程任务类实现Callable接口,申明线程执行的结果类型
class MyCallable implements Callable<String>{

    //2.重写线程任务类的call方法,这个方法可以直接返回执行结果
    @Override
    public String call() throws Exception {
        System.out.println("hello callable");
        return "success";
    }
}
java 复制代码
//3.创建一个Callable的线程任务对象
Callable<String> call = new MyCallable();
//4.把线程任务对象包装成一个未来任务对象
//-- 未来任务对象其实就是一个Runable对象,这样就可以被包装成线程对象
//-- 未来任务对象可以在线程执行完毕后得到线程执行结果
FutureTask<String> future = new FutureTask<>(call);

//5.把未来任务对象包装成线程对象
Thread t = new Thread(future);
t.start();

//获取线程执行结果,如果线程还没执行完,让出CPU等线程执行完再来去结果
try {
    String res = future.get();
    System.out.println(res);
} catch (InterruptedException e) {
    e.printStackTrace();
} catch (ExecutionException e) {
    e.printStackTrace();
}

优点:

  • 拥有所有Runable的优点
  • 能直接得到线程执行的结果

缺点:

  • 编码复杂
相关推荐
皮皮林5519 小时前
IDEA 源码阅读利器,你居然还不会?
java·intellij idea
卡尔特斯14 小时前
Android Kotlin 项目代理配置【详细步骤(可选)】
android·java·kotlin
白鲸开源14 小时前
Ubuntu 22 下 DolphinScheduler 3.x 伪集群部署实录
java·ubuntu·开源
ytadpole14 小时前
Java 25 新特性 更简洁、更高效、更现代
java·后端
纪莫14 小时前
A公司一面:类加载的过程是怎么样的? 双亲委派的优点和缺点? 产生fullGC的情况有哪些? spring的动态代理有哪些?区别是什么? 如何排查CPU使用率过高?
java·java面试⑧股
JavaGuide15 小时前
JDK 25(长期支持版) 发布,新特性解读!
java·后端
用户37215742613515 小时前
Java 轻松批量替换 Word 文档文字内容
java
白鲸开源15 小时前
教你数分钟内创建并运行一个 DolphinScheduler Workflow!
java
Java中文社群16 小时前
有点意思!Java8后最有用新特性排行榜!
java·后端·面试
代码匠心16 小时前
从零开始学Flink:数据源
java·大数据·后端·flink