Java 中创建线程几种方式

news2024/11/14 22:28:10

目录

概述

一. 继承Thread类

1. 特点

2. 注意事项

3. 代码示例

二. 实现Runnable接口

1. 特点

2. 注意事项

3. 代码示例

三. 实现Callable接口

1. 特点

2. 注意事项

3. 代码示例


概述

在Java中,线程(Thread)是程序执行的最小单元,它允许程序在同一时间执行多个任务。Java中的线程可以由Thread类创建,也可以通过实现Runnable接口或Callable接口创建。

java中线程几种状态:

  1. 新建(New): 线程对象已经被创建,但还没有调用start()方法。

  2. 可运行(Runnable): 线程已经调用了start()方法,但还没有获得CPU时间片执行。可运行状态包括了操作系统线程的就绪(Ready)和运行(Running)状态。

  3. 阻塞(Blocked): 线程因为等待监视器锁而被阻塞,无法继续执行。

  4. 等待(Waiting): 线程通过调用wait()join()LockSupport.park()等方法进入等待状态,需要其他线程通知或中断后才可能继续执行。

  5. 超时等待(Timed Waiting): 线程通过调用带有超时参数的sleep()wait()join()LockSupport.parkNanos()LockSupport.parkUntil()等方法进入超时等待状态,超时后会自动唤醒。

  6. 终止(Terminated): 线程的run()方法执行结束,或者因异常退出了run()方法。

线程的状态枚举类 State

一. 继承Thread类

通过继承Thread类并重写run方法来创建线程,本质上继承Thread类实现线程的方式也是通过实现 Runnable 接口,

1. 特点

  • 简单性:实现线程的代码简单直观。
  • 局限性:由于Java的单继承特性,如果一个类已经继承了其他类,就不能再继承Thread类。

2. 注意事项

  • 不要调用Thread类的run方法:应该重写run方法,而不是直接调用它。
  • 使用start方法启动线程start方法会创建一个新的线程,并调用run方法。
  • 线程安全:如果线程之间需要共享数据,需要考虑线程安全问题。

3. 代码示例

package com.demo.thread;

/**
 * 文件名:ThreadDemo
 * 创建者:
 * 创建时间:2024-09-22
 * 描述: 通过继承 Thread 类并重写run方法来创建线程
 */
public class ThreadDemo extends Thread{
    @Override
    public void run(){
        System.out.println(Thread.currentThread().getName()+"-执行run方法");
    }
}

/**
 * 测试类
 */
class MainThread{
    public static void main(String[] args) {
        //1.第一种方式创建线程
        Thread thread = new Thread(new ThreadDemo(),"线程1");
        thread.start(); //启动线程

        //2.第二种方式创建线程
        Thread thread2 = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName()+"-执行run方法");
            }
        },"线程2");
        thread2.start(); //启动线程
    }
}


二. 实现Runnable接口

实现 Runnable 接口是Java中创建线程的另一种常见方式,这种方式更加灵活,因为它允许类继承其他类的同时实现线程功能。Runnable 接口定义了一个 run 方法,这是线程执行的入口点。

1. 特点

  • 灵活性:实现 Runnable 接口允许类继承其他类,同时实现多线程功能。
  • 线程安全:如果多个线程共享同一个 Runnable 实例,需要考虑线程安全问题。

2. 注意事项

  • 不要在 run 方法中调用 Thread.currentThread().stop():这是不推荐的做法,因为它可能会导致程序处于不确定状态。
  • 异常处理:在 run 方法中妥善处理异常,避免线程意外终止。
  • 资源清理:如果线程使用了一些资源(如文件句柄、数据库连接等),确保在线程结束时释放这些资源。

3. 代码示例

package com.demo.thread;

/**
 * 文件名:RunnableDemo
 * 创建者:
 * 创建时间:2024-09-22
 * 描述:实现 Runnable接口创建线程
 */
public class RunnableDemo implements Runnable{
    public void run() {
        System.out.println(Thread.currentThread().getName()+"-"+"执行run方法");
    }
}

/**
 * 测试类
 */
class MainDemo{
    public static void main(String[] args) {
        //1.第一种创建线程执行
        Thread thread = new Thread(new RunnableDemo(),"线程1");
        thread.start(); // 启动线程

        //2.第二种创建线程执行
        Thread thread2 = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName()+"-执行run方法");
            }
        },"线程2");
        thread2.start(); // 启动线程

    }
}

三. 实现Callable接口

当我们需要创建一个可以返回结果的线程时,就可以使用实现了Callable接口的方式。Callable接口是在Java 5中引入的,它允许线程执行一个任务并返回一个结果,与Runnable接口相比,Callable接口的call()方法可以返回结果并抛出异常。

Callable 接口与 Runnable 接口类似,但它可以返回一个结果并且能抛出异常。Callable 通常与 FutureTask 一起使用,后者实现了 Runnable 接口,并且包装了 Callable 对象。

1. 特点

  • 返回结果Callable 任务可以返回一个结果,可以通过 FutureTask.get() 方法获取。
  • 抛出异常Callable 任务可以抛出异常,可以通过 FutureTask.get() 方法捕获。

2. 注意事项

  • 异常处理:在 call 方法中抛出的异常可以通过 FutureTask.get() 方法的调用者捕获。
  • 线程安全:如果 Callable 任务需要访问共享资源,需要考虑线程安全问题。

3. 代码示例

使用步骤:

  1. 创建一个实现 Callable 接口的类
  2. 实现 Callable 接口的 call 方法,该方法是线程执行的入口点。
  3. 创建 Callable 实例
  4. Callable 实例传递给 FutureTask 的构造器
  5. FutureTask 对象传递给 Thread 类的构造器
  6. 创建 Thread 对象
  7. 调用 Thread 对象的 start 方法来启动线程。
  1. 简单使用
    package com.demo.thread;
    
    import java.util.concurrent.Callable;
    import java.util.concurrent.ExecutionException;
    import java.util.concurrent.FutureTask;
    
    /**
     * 文件名:CallableDemo
     * 创建者:
     * 创建时间:2024-09-22
     * 描述:通过 Callable 接口实现线程创建
     */
    public class CallableDemo implements Callable<String> {
        @Override
        public String call() throws Exception {
            return "测试";
        }
    }
    
    /**
     * 测试类
     */
    class MainCallable{
        public static void main(String[] args){
            //1.创建对象
            CallableDemo demo = new CallableDemo();
            FutureTask<String> futureTask = new FutureTask<>(demo);
            //2.创建线程
            Thread thread = new Thread(futureTask);
            thread.start();
            //3.获取返回结果
            String res;
            try {
                res = futureTask.get();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            } catch (ExecutionException e) {
                throw new RuntimeException(e);
            }
            System.out.println("获取线程返回结果:"+res);
        }
    }
    
    
  2. 通过线程池使用
    package com.demo.thread;
    
    import java.util.concurrent.Callable;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.Future;
    
    /**
     * 文件名:Main
     * 创建者:
     * 创建时间:2024-09-22
     * 描述:
     */
    public class Main {
        public static void main(String[] args) {
            //1.创建一个线程池
            ExecutorService executorService = Executors.newSingleThreadExecutor();
            //2.创建Callable任务
            Callable<String> callableTask = () -> {
                Thread.sleep(2000); // 模拟长时间运行的任务
                return "测试";
            };
            //3.提交Callable任务并获取Future对象
            Future<String> future = executorService.submit(callableTask);
            try {
                //3.获取异步任务的执行结果
                String result = future.get(); //此方法会阻塞,直到任务执行完成
                System.out.println("任务执行结果: " + result);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                //4.关闭线程池
                executorService.shutdown();
            }
        }
    }
    

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2161712.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java面试篇基础部分-Synchronized关键字详解

Synchronized关键字用于对Java对象、方法、代码块等提供线程安全操作。Synchronized属于独占式的悲观锁机制,同时也是可重入锁。我们在使用Synchronized关键字的时候,可以保证同一时刻只有一个线程对该对象进行访问;也就是说它在同一个JVM中是线程安全的。   Java中的每个…

mask controlnet

diffusers/examples/controlnet/README.md at main huggingface/diffusers GitHub🤗 Diffusers: State-of-the-art diffusion models for image and audio generation in PyTorch and FLAX. - diffusers/examples/controlnet/README.md at main huggingface/diffusershttp…

怎么在Proteus中找到排阻

1、打开安装好的Proteus&#xff0c;点击上方菜单栏中的“库”&#xff0c;再选择“从库选取零件”&#xff0c;或者在左侧元件列表中单击鼠标右键&#xff0c;再点击右键菜单中的“从库中挑选”选项。 2、之后会打开元器件库&#xff0c;我们打开类别中的“Resistors”&#x…

《深度学习》CNN 数据增强、保存最优模型 实例详解

目录 一、数据增强 1、什么是数据增强 2、目的 3、常用的数据增强方法 4、数据预处理 用法&#xff1a; 5、使用数据增强增加训练数据 二、保存最优模型 1、什么是保存最优模型 2、定义CNN模型 运行结果&#xff1a; 3、设置训练模式 4、设置测试模式、保存最优模…

RHCS认证-Linux(RHel9)-Ansible

文章目录 一、ansible 简介二 、ansible部署三、ansible服务端测试四 、ansible 清单inventory五、Ad-hot 点对点模式六、YAML语言模式七、RHCS-Ansible附&#xff1a;安装CentOS-Stream 9系统7.1 ansible 执行过程7.2 安装ansible&#xff0c;ansible-navigator7.2 部署ansibl…

点亮一个LED灯

一、任务分析 一个灯怎么样才会亮&#xff1f; 图中的小灯两端接正负极&#xff0c;小灯就会点亮&#xff0c;但是我们不能主动控制灯的亮灭&#xff0c;于是加入了开关。开关打开断开小灯正极&#xff0c;小灯就会熄灭&#xff0c;反之则点亮。 在板子上的灯是如何连接的&…

Spring Boot集成Redis向量数据库实现相似性搜索

1.什么是Redis向量数据库&#xff1f; Redis 是一个开源&#xff08;BSD 许可&#xff09;的内存数据结构存储&#xff0c;用作数据库、缓存、消息代理和流式处理引擎。Redis 提供数据结构&#xff0c;例如字符串、哈希、列表、集合、带范围查询的有序集合、位图、超对数日志、…

Qt开发-comboBox 所有槽函数介绍(2024.09)

activated(int): 触发于ComboBox中某一项被激活时&#xff0c;参数为该项的索引。 currentIndexChanged(QString)/currentIndexChanged(int): 当前选中项变化时触发&#xff0c;前者传递文本&#xff0c;后者传递索引。 currentTextChanged(QString): 当前选中项的文字变更时触…

Ubuntu 与Uboot网络共享资源

1、NFS 1.1 Ubuntu 下 NFS 服务开启 sudo apt-get install nfs-kernel-server rpcbind 等待安装完成&#xff0c;安装完成以后在用户根目录下创建一个名为“Linux”的文件夹&#xff0c;以后所有 的东西都放到这个“Linux”文件夹里面&#xff0c;在“Linux”文件夹里面新建…

Qt获取本机Mac地址、Ip地址

一、简述 今天给大家分享一个获取本机IP地址和Mac地址的方法&#xff0c;经过多次测试&#xff0c;台式机、笔记本等多个设备&#xff0c;暂时没有发现问题。 由于很多时候本地安装了虚拟机、蓝牙、无线网卡或者其他设备等&#xff0c;会有多个Mac地址&#xff0c;所以需要进…

【828华为云征文|如何轻松部署“未知表白墙”项目:华为云Flexus X实例指南】

文章目录 华为云 Flexus X 实例&#xff1a;开启高效云服务的新纪元部署【未知表白墙】项目准备工作具体操作指南服务器环境确认宝塔软件商店操作域名解析未知表白墙登录页修改管理员账号和密码未知表白墙管理页面基础设置表白管理 未知表白墙效果查看 总结 华为云 Flexus X 实…

c++924

2 #include <iostream> #include <cstring>using namespace std;class MyString { private:char *str; // 记录C风格的字符串int size; // 记录字符串的实际长度public:// 定义无参构造MyString() : size(0) {str new char[1];str[0] \0;cou…

Unity中Rigidbody 刚体组件和Rigidbody类是什么?

Rigidbody 刚体组件 Rigidbody 是 Unity 中的一个组件&#xff0c;它可以让你的游戏对象像真实世界中的物体一样移动和碰撞。想象一下&#xff0c;你有一个小球&#xff0c;你希望它像真实世界中的球一样滚动、弹跳和碰撞&#xff0c;那么你就可以给这个小球添加一个 Rigidbod…

JavaScript中的日期和时间

日期和时间 JS语言核心包括Date()构造函数&#xff0c;用来创建表示日期和时间的对象。提供了简单的API. 代码实现&#xff1a; <!DOCTYPE html> <html><head><meta charset"utf-8"><title>3.1.5 日期和时间</title></hea…

3D模型在UI设计中应用越来越多,给UI带来了什么?

当前3D模型在UI设计中应用很多&#xff0c;极大地拓展了UI设计的发挥空间&#xff0c;也拓宽了UI的应用领域&#xff0c;本文分享下UI中引入3D模型到底能带来什么价值. 3D模型在UI设计中的应用可以给用户界面带来以下几个方面的好处&#xff1a; 更真实的视觉体验&#xff1a;…

【2024W36】肖恩技术周刊(第 14 期):什么是完美副业?

周刊内容: 对一周内阅读的资讯或技术内容精品&#xff08;个人向&#xff09;进行总结&#xff0c;分类大致包含“业界资讯”、“技术博客”、“开源项目”和“工具分享”等。为减少阅读负担提高记忆留存率&#xff0c;每类下内容数一般不超过3条。 更新时间: 星期天 历史收录:…

2016年国赛高教杯数学建模C题电池剩余放电时间预测解题全过程文档及程序

2016年国赛高教杯数学建模 C题 电池剩余放电时间预测 铅酸电池作为电源被广泛用于工业、军事、日常生活中。在铅酸电池以恒定电流强度放电过程中&#xff0c;电压随放电时间单调下降&#xff0c;直到额定的最低保护电压&#xff08;Um&#xff0c;本题中为9V&#xff09;。从充…

TAPD多类别需求管理

本文档将介绍&#xff1a;什么是 TAPD 多类别需求管理&#xff0c;以及如何配置或创建新的需求类别。 一、概述 在研发管理过程中&#xff0c;团队经常会遇到规模扩张、不同特性团队间研发模式差异化大等问题。以上问题导致团队中的需求无法进行统一管理。为解决上述情况&…

54 螺旋矩阵

解题思路&#xff1a; \qquad 这道题可以直接用模拟解决&#xff0c;顺时针螺旋可以分解为依次沿“右-下-左-上”四个方向的移动&#xff0c;每次碰到“边界”时改变方向&#xff0c;边界是不可到达或已经到达过的地方&#xff0c;会随着指针移动不断收缩。 vector<int>…

Adobe Illustrator吸管工具提取的颜色与原色之间存在色差

问题原因&#xff1a; 被提取颜色的对象是外部链接图片&#xff0c;对其提取的颜色会与AI中看到的颜色不同 如下图所示&#xff0c;中间的矩形与外部矩形的内部颜色存在色差 解决办法&#xff1a; 方法一&#xff1a;将该外部图片利用屏幕截图的形式&#xff0c;粘贴到AI中。…