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

java · 浏览次数 : 10

小编点评

继承Thread类和实现Runnable接口是创建线程的两种方式。继承Thread类可以实现多继承,但限制了只能有一个父类,而实现Runnable接口可以实现多个接口,具有更大的灵活性。在具体应用中,可以根据需求选择合适的方式。 如果需要获得线程执行结果,可以选择实现Callable接口的方式。Callable接口可以声明线程执行的结果类型,并重写call方法来返回执行结果。使用FutureTask将线程任务包装成未来任务对象,然后将其作为线程对象运行,这样可以在线程执行完成后获取结果。

正文

一、继承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()方法启动线程
class MyRunable implements Runnable{

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

优点:

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

缺点

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

匿名内部类的写法:

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()方法启动线程
//1.定义一个线程任务类实现Callable接口,申明线程执行的结果类型
class MyCallable implements Callable<String>{

    //2.重写线程任务类的call方法,这个方法可以直接返回执行结果
    @Override
    public String call() throws Exception {
        System.out.println("hello callable");
        return "success";
    }
}
//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的优点
  • 能直接得到线程执行的结果

缺点:

  • 编码复杂

与Java基础:线程的三种创建方式相似的内容:

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

一、继承Thread类 定义一个类继承线程类Thread 重写run()方法 创建线程对象 调用线程对象的start()方法创建线程 Thread类的常用API setName(String name):给线程取名字 getName():获取线程的名字 public static Thread cu

多线程知识:三个线程如何交替打印ABC循环100次

本文博主给大家讲解一道网上非常经典的多线程面试题目。关于三个线程如何交替打印ABC循环100次的问题。 > 下文实现代码都基于Java代码在单个JVM内实现。 ## 问题描述 给定三个线程,分别命名为A、B、C,要求这三个线程按照顺序交替打印ABC,每个字母打印100次,最终输出结果为: ``` A

4.7 C++ Boost 多线程并发库

C++语言并没有对多线程与网络的良好支持,虽然新的C++标准加入了基本的`thread`库,但是对于并发编程的支持仍然很基础,Boost库提供了数个用于实现高并发与网络相关的开发库这让我们在开发跨平台并发网络应用时能够像Java等语言一样高效开发。thread库为C++增加了多线程处理能力,其主要提供了清晰的,互斥量,线程,条件变量等,可以很容易的实现多线程应用开发,而且该库是可跨平台的,并且支持

Java多线程

一.线程的生命周期及五种基本状态 关于Java中线程的生命周期,首先看一下下面这张较为经典的图: 上图中基本上囊括了Java中多线程各重要知识点。掌握了上图中的各知识点,Java中的多线程也就基本上掌握了。主要包括: Java线程具有五中基本状态 新建状态(New):当线程对象对创建后,即进入了新建

JAVA多线程并发编程-避坑指南

本篇旨在基于编码规范、工作中积累的研发经验等,整理在多线程开发的过程中需要注意的部分,比如不考虑线程池参数、线程安全、死锁等问题,将会存在潜在极大的风险。并且对其进行根因分析,避免每天踩一坑,坑坑不一样。

Spring Reactor基本介绍和案例

1. Reactor 对比 1.1 Reactor 线程模型 Reactor 线程模型就是通过 单个线程 使用 Java NIO 包中的 Selector 的 select()方法,进行监听。当获取到事件(如 accept、read 等)后,就会分配(dispatch)事件进行相应的事件处理(han

Java基础:throw和throws的详解

总结来说,throw是用来抛出一个具体的异常实例,而throws是用来声明方法可能会抛出哪些类型的异常,是对调用者的一种通知和要求。 1. throw 作用: throw关键字用于在方法体内实际抛出一个异常实例。当程序运行到throw语句时,指定的异常会被创建并抛出,立即终止当前方法的执行,并将控制

Java基础 韩顺平老师的 常用类 的部分笔记

459,八大Wrapper类 包装类的分类 1) 针对八种基本数据类型相应的引用类型—包装类 2) 有了类的特点, 就可以调用类中的方法。 460,装箱和拆箱 package com.hspedu.Wrapper; public class WrapperType { public static v

java基础 韩顺平老师的 异常 自己记的部分笔记

443,异常处理入门 package com.hspedu.exception_; public class Exception { public static void main(String[] args) { int num1 = 10; int num2 = 0; //老韩解读 //1,nu

Fastjson基础环境配置与Java基础概念

Preface 此篇系列文章将会从 Java 的基础语法开始,以 Fastjson 的各个反序列化漏洞分析为结尾,详细记录如何从一个具有基础面向对象编程但毫无 Java 基础的小白成长为了解 Fastjson 的各个漏洞并能够熟练利用的网络安全人员。 环境配置 我们使用 IDEA 作为开发的 IDE