首页 > 编程语言 >线程介绍及其Java如何用Thread 类创建线程和操作线程方法

线程介绍及其Java如何用Thread 类创建线程和操作线程方法

时间:2024-06-11 20:57:44浏览次数:13  
标签:run Thread 创建 void 线程 new Java

目录

一、进程和线程

进程和线程有什么关系?

1.1 进程

  • 进程是操作系统中的一种资源分配单位,它是操作系统中一个独立的执行单元。
  • 进程是电脑资源分配的最小单位。
  • 进程中至少有一个线程。
特征
  • 独立性:每个进程都是独立的执行单元,拥有自己的内存空间和系统资源。
  • 资源分配:操作系统将资源分配给进程,例如内存、CPU 时间等。
  • 执行:进程可以执行不同的任务,例如运行应用程序、提供服务等。

2.2 线程

  • 线程是进程中的一个执行单元。
  • 线程是资源调度的最小单位
特征
  • 轻量级:线程比进程更加轻量级,创建和销毁线程的开销远小于进程。
  • 共享资源:多个线程可以共享同一个进程的资源,如内存、文件等。
  • 高效:线程可以提高程序的响应速度和系统的吞吐量。

2.3 区别

  • 资源分配:进程拥有自己的内存空间和系统资源,而线程共享进程的资源。
  • 执行:进程可以执行不同的任务,而线程执行的是进程中的某个任务。
  • 开销:创建和销毁进程的开销远大于线程。

下面着重讲一下Java如何创建线程


二、利用Thread类创建线程

有三种方法创建

2.1 通过创建Thread子类,重写run()方法

  • 通过创建子类实现
  • 通过匿名内部类实现
    public static void main(String[] args) {
        for (int i = 0; i < 100; i++) {
            System.out.println("main线程---->"+ i);
        }
        //匿名内部类
        new Thread(){
            @Override
            public void run() {
                for (int i = 100; i < 200; i++) {
                    System.out.println("创建线程----》"+ i);
                }
            }
        }.start();
        // 创建子类对象实现
        new MyThread().start();


    }
}

2.2 通过实现Runnable接口,重写run()方法

  • 通过实现类实现
  • 通过匿名内部类实现
 public static void main(String[] args) {
        /*
         * 1.创建Runnable接口实现类对象,并重写run方法
         * 2.创建Thread对象
         * 3.开启线程
         */

        //创建实现类对象
        MyRunnable myRunnable = new MyRunnable();
        //创建Thread对象
        Thread thread = new Thread(myRunnable);
        //开启线程
        thread.start();

        //使用匿名内部类实现
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                System.out.println("匿名线程");
            }
        };
        //创建Thread对象
        Thread thread2 = new Thread(runnable);
        //开启线程
        thread.start();
    }

2.3. Callable接口 + FutureTask 创建线程

 public static void main(String[] args) throws ExecutionException, InterruptedException {

        /*
         * 五个步骤
         * 1.创建Callable子实现类对象
         * 2.创建FutureTask对象
         * 3.创建Thread对象
         * 4.开启多线程
         * 5.获得返回值  注意:一定要先开启线程,才能获得返回值
         */

        // 普通方法实现
        MyCallable myCallable = new MyCallable();// 创建Callable子实现类对象
        FutureTask<Integer> task = new FutureTask<>(myCallable);// 创建FutureTask对象,并将Callable子实现类作为参数传入
        Thread thread = new Thread(task); // 创建Thread对象,传入FutureTask对象参数
        thread.start(); // 开启多线程
        System.out.println(task.get()); // 获得返回值,并打印

        // 通过匿名内部类实现
        FutureTask<Integer> task1 = new FutureTask<>(new Callable<Integer>() { // 通过匿名内部类实现Callable接口
            @Override
            public Integer call(){ // 重写Callable接口call() 方法
                return 22;
            }
        });
        new Thread(task1).start(); //创建Thread对象,并开启多线程
        System.out.println(task1.get());// 获得返回值,并打印
}

2.3 三种方法区别

1. 通过创建Thread子类,重写run()方法
简单,但是要继承,子类就不能在继承其他类了,使用后扩展性较低
2. 通过实现Runnable接口,重写run()方法
步骤较复杂,且重写的run()方法没有返回值,没有传入参数,功能较简单,但是相对于Thread扩展性较高
3. Callable接口 + FutureTask 创建线程
步骤相对复杂,但是线程具有返回值和参数,方法功能性较强

三、关于线程常用操作方法

3.1 操作线程名字方法

方法签名方法描述
void setName(String name)改变线程名称,使之与参数 name 相同
Thread(String name)分配新的 Thread 对象,名字与参数相同
String getName()获得线程名字,并返回
代码演示

        // 获得当前线程对象
        Thread currentThread = Thread.currentThread();
        // 获得线程名字
        String name = currentThread.getName();
        System.out.println(name);// main

        // 创建新线程 三种方法
        // 创建Thread子类方法
        Thread newThread = new Thread(){
            @Override
            public void run() {
                System.out.println("newThread");
            }
        };
        // 获得名字
        String name1 = newThread.getName();
        // 默认为Thread-0,那么下一个使用无参构造方法创建的对象名字为:Thread-1,以此类推...
        System.out.println(name1);//Thread-0
        // 设置名字
        newThread.setName("newThread");
        System.out.println(newThread.getName());//newThread

3.2 获得当前线程

方法签名方法描述
static Thread currentThread()返回对当前正在执行的线程对象的引用
代码演示
 		 // 获得当前线程对象
        Thread currentThread = Thread.currentThread();
        // 获得线程名字
        String name = currentThread.getName();
        System.out.println(name);// main

3.3 线程优先级

方法签名方法描述
void setPriority(int newPriority)更改线程的优先级
int getPriority()返回线程的优先级
代码演示
Thread t1 = new Thread("T1") {
            @Override
            public void run() {
                for (int i = 1; i < 101; i++) {
                    System.out.println(getName()+"执行-->" +i );
                }
            }
        };
        // 返回线程的优先级 
        int i = t1.getPriority();
        System.out.println(i);// 5 默认为5
        t1.setPriority(1);
   
注意
优先级只是相对来说的,优先级大的先执行的概率大,并不是优先级大就一定先执行

3.4 守护线程

方法签名方法描述
boolean setDaemon(boolean n)将该线程标记为守护线程或用户线程
注意:
  • 需要在开启线程前,调用方法
  • 设置成功后,该线程为守护线程,除外其他所以线程均为被守护线程
  • 被守护线程停止,守护线程也将停止
代码演示
 Runnable runnable = new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 100; i++) {
                    System.out.println("小兵" + i + "在战斗");
                }
            }
        };
        //创建对象
        Thread thread = new Thread(runnable);
        //设置守护
        thread.setDaemon(true);
        //开启线程
        thread.start();

        Runnable runnable1= new Runnable() {
            @Override
            public void run() {
                System.out.println("大王战死");
            }
        };
        //创建对象,并开启线程
        new Thread(runnable1).start();
结果:

在这里插入图片描述

3.5 线程休眠

方法签名方法描述
static void sleep(long millis)在指定的毫秒数内让当前正在执行的线程休眠(暂停执行)
代码演示
 Thread t2 = new Thread("行人") {
        @Override
        public void run() {
            for (int i = 1; i < 1001; i++) {
                System.out.println("行人" + i + "执行...");
            }
        }
    };

    Thread t1 = new Thread("汽车") {
        @Override
        public void run() {
            for (int i = 1; i < 1001; i++) {
                if (i == 100){
                    try {
                        /**
                         * 让当前线程休眠
                         * 让出系统资源,别的线程执行
                         * 等当前线程休眠结束,继续执行
                         */
                        Thread.sleep(1);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
                System.out.println("汽车" + i + "执行...");
            }
        }
    };

结果:

在这里插入图片描述

3.6 礼让线程

方法签名方法描述
static void yield()暂停当前正在执行的线程对象,并执行其他线程

3.7 插入(加入)线程

方法签名方法描述
void join()无限制时间加入,直到线程结束
void join(long millis)等待该线程终止的时间最长为 millis 毫秒
代码演示
        Thread t2 = new Thread("行人") {
            @Override
            public void run() {
                for (int i = 1; i < 1001; i++) {
                    System.out.println("行人" + i + "执行...");
                }
            }
        };

        Thread t1 = new Thread("汽车") {
            @Override
            public void run() {
                for (int i = 1; i < 1001; i++) {
                    if (i == 100){
                        try {
                            //t2.join();// 让线程2加入,直到线程2执行完毕,线程1才会继续
                            t2.join(1);// 让线程2加入,但是线程2只运行1毫秒,1毫秒后,线程1 2继续争抢
                        } catch (InterruptedException e) {
                            throw new RuntimeException(e);
                        }
                    }
                    System.out.println("汽车" + i + "执行...");
                }
            }
        };
        t1.start();
        t2.start();
    

3.8 停止/中断线程

方法签名方法描述
void stop()停止线程(该方法已过时)
void interrupt()中断线程

四、线程状态

  • 五种状态
    在这里插入图片描述

思维导图

  • 下面时该文章的思维导图,可以看一下

在这里插入图片描述


最后

如果感觉有收获的话,点个赞

标签:run,Thread,创建,void,线程,new,Java
From: https://blog.csdn.net/m0_73940426/article/details/139607339

相关文章

  • 基本数据类型 String,null 和 undefined,运算符,流程控制,JavaScript之数组,数组常用
    Ⅰ基本数据类型String【一】String类型String类型就是字符串类型【二】定义变量【1】常规变量var变量名="变量值";//一般用这种var变量名='变量值';不支持三引号【2】可以先声明不赋值先用varb;再对变量b赋值varb='6';【三】字符串的格式化输出语法......
  • 神奇的JavaScript弱等价类型转换
    JavaScript语言特性-类型转换JavaScript这门语言的类型系统从来没有它表面看起来的那样和善,虽然比起Java、C#等一众强类型语言,它的弱类型使用起来似乎是如此便利,但正因为它极高的自由度,所以才会衍生出令人摸不着头脑的荒诞行为。举个例子,虽然我们都知道一个包含内容的字符串会......
  • C#实现多线程的几种方式(附完整源码)
    C#实现多线程的几种方式1.使用Thread类:2.使用ThreadPool类:3.使用Task类:以下是C#中实现多线程的几种常见方式的示例代码:1.使用Thread类:usingSystem;usingSystem.Threading;​classProgram{staticvoidMain(){Threadth......
  • 探索Java的奥秘:网络编程、反射与注解的深度解析
    Java,作为一门功能强大的编程语言,在网络编程、反射和注解方面提供了丰富的支持和灵活的应用。本文将深入探讨这些概念,并通过实际例子来加深理解。一、Java网络编程1.1网络编程基础网络编程是Java语言的一大亮点,它允许我们创建能够通过网络进行通信的程序。Java提供了java......
  • 大学生HTML期末大作业——HTML+CSS+JavaScript美食网站(零食)
    HTML+CSS+JS【美食网站】网页设计期末课程大作业web前端开发技术web课程设计网页规划与设计......
  • 大学生HTML期末大作业——HTML+CSS+JavaScript购物商城(华为手机)
    HTML+CSS+JS【购物商城】网页设计期末课程大作业web前端开发技术web课程设计网页规划与设计......
  • Java中List集合中多个字段如何排序
    开源项目SDK:https://github.com/mingyang66/spring-parent个人文档:https://mingyang66.github.io/raccoon-docs/#/一、首先定义一个三个属性的People类publicclassPeople{privateStringname;privateintage;privateintheight;publicPeople......
  • 【数据库】mybatis生成java代码之AutoGenerator配置
    哈喽,大家好,我是木头左,AI改变生活!本文将详细解释MyBatis生成Java代码的过程,包括全局配置、数据源配置和策略配置。1.全局配置首先,我们需要创建一个GlobalConfig对象,用于配置MyBatis的全局设置。以下是一些常用的全局配置选项:setOutputDir(StringoutputDir):设置生......
  • Java项目:208Springboot + vue实现的校园服务平台(含论文+开题报告)
    作者主页:夜未央5788 简介:Java领域优质创作者、Java项目、学习资料、技术互助文末获取源码项目介绍基于Springboot+vue实现的汽车服务管理系统本系统包含管理员、接单员、普通用户三个角色。管理员角色:管理员管理、基础数据管理、接单详情管理、接单员管理、公告信......
  • C# JavaScriptSerializer序列化时的时间处理详解
    原文链接:https://www.jb51.net/article/122143.htm输出如下图所示: 猜测这里是由于js初始化时间的时候往往是向1970/01/01添加毫秒数,JavaScriptSerializer进行序列化的时候也会格式化为距离1970/01/01到当该时间点GMT+0时间的毫秒数,如果直接反序列化可以看到少了8小时,且......