java EE初阶 — 如何进行多线程编程

news2024/11/29 10:44:43

文章目录

  • 1.java如何进行多线程编程
    • 1.1 最基础的多线程代码
    • 1.2 线程的优势
  • 2.java中创建线程的方法
    • 2.1 继承Thread 重写run
    • 2.2 实现Runnable 接口
    • 2.3 使用匿名的内部类,继承 Thread
    • 2.4 使用匿名类。继承 Runnable
    • 2.5 使用 Lambda 表达式(最简答、最推荐)

1.java如何进行多线程编程

Thread 是java操作多线程最核心类。
使用Thread不需要import导入别的包,因为它是在java.lang下面

1.1 最基础的多线程代码

package thread;

class MyThread extends Thread{
    //在此类中重写run方法
    @Override
    public void run() {
        System.out.println("hello world");
    }
}

public class ThreadDemo1 {

    public static void main(String[] args) {
        Thread thread = new MyThread();
        thread.start();//线程中的特殊方法 - 创建一个线程
    }
}

thread包中创建一个对象,Mythread子类继承Thread父类
重写Thread类中的run方法输出hello world。
start是线程中的特殊方法,在这里的作用是创建一个新的线程,而不是调用run。
新的线程负责调用run方法来输出hello world。


新的进程调用操作系统的API,通过操作系统内核创建新线程的PCB。
并且把要执行的指令交给这个PCB。
当这个PCB被调度到CPU上的时候,也就执行到了线程run方法中的代码了。

如果run方法执行完毕,这个新的线程会销毁。

1.2 线程的优势

改动一下上面的代码:

package thread;

class MyThread extends Thread{
    //在此类中重写run方法
    @Override
    public void run() {
        while (true) {
            System.out.println("hello world");
        }
    }
}

public class ThreadDemo1 {

    public static void main(String[] args) {
        Thread thread = new MyThread();
        thread.start();//线程中的特殊方法 - 创建一个线程
        while (true) {
            System.out.println("hello java");
        }
    }
}

如果此时的代码时非线程的,程序会死循环的输出 hello world,并且没有机会执行 hello java
但是实际情况是,这两条输出语句都会执行,并且都是死循环

为了方便观察,调用sleep设置睡眠时间为1秒。

package thread;

class MyThread extends Thread{
    //在此类中重写run方法
    @Override
    public void run() {
        while (true) {
            System.out.println("hello world");
            //睡一会儿
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

public class ThreadDemo1 {

    public static void main(String[] args) {
        Thread thread = new MyThread();
        thread.start();//线程中的特殊方法 - 创建一个线程
        while (true) {
            System.out.println("hello java");
            //睡一会儿
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}


先执行 hello world 还是先执行 hello java 是不确定的。
操作系统调度线程的时候,是“抢占式执行的”,具体哪个先哪个后,是不确定的。
这要取决与操作系统的调度器具体的实现策略。

虽然有优先级,但是在应用程序层面上无法修改。
从应用程序(代码)的角度,看到的效果,就好像是线程的调度效果好像是随机的一样。

内核里本身并不是随机的,但是干预的元素太多了,并且应用程序这一层也无法感知到细节,就只能认为是随机的了。

抢占式执行,随机访问就是线程安全问题的罪魁祸首。


如果其中一条语句无法输入,不会影响另一条语句。

把输出 hello world 的语句给屏蔽了,但是不会影响输出 hello java

class MyThread extends Thread{
    //在此类中重写run方法
    @Override
    public void run() {
        while (true) {
            //System.out.println("hello world");
            //睡一会儿
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}


就像是,张三和李四去学校,张三不来了并不会决定李四来不来。


start 和 run 之间的区别:

start是真正上创建了一个进程(从系统这里创建的),线程是独立的执行流。

run只是描述了线程要干的活是什么,如果直接在main中调用 run 。
此时没有创建新线程,全是main线程一个人干活。

2.java中创建线程的方法

2.1 继承Thread 重写run


第一种方法就是前面介绍的方法。

2.2 实现Runnable 接口

package thread;

//Runnable 的作用是描述一个要“执行的任务”,run方法就是任务的执行细节
class MyRunnable implements Runnable {
    @Override
    public void run() {
        System.out.println("hello 张三");
    }
}

public class ThreadDemo2 {
    public static void main(String[] args) {
        //这只是描述了任务
        Runnable runnable = new MyRunnable();
        //把任务交给线程来执行
        Thread thread = new Thread(runnable);
        thread.start();
    }
}

如果未来要更改代码,不用多线程,
而是使用多进程,或者线程池、协程…此时的代码改动比较小。

2.3 使用匿名的内部类,继承 Thread

package thread;

public class ThreadDemo3 {
    public static void main(String[] args) {
        Thread thread = new Thread() {
            @Override
            public void run() {
                System.out.println("haha");
            }
        };
        thread.start();
    }
}

上面方法先是创建了一个Thread的子类(子类没有名字),所以才叫做匿名。
然后是创建了子类的实例,并且让thread引用指向该实例。

2.4 使用匿名类。继承 Runnable

package thread;

public class ThreadDemo4 {
    public static void main(String[] args) {
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("hehehehe");
            }
        });
        thread.start();
    }
}

这个写法本质和2相同。
只不过是把实现 Runnable 任务交给了匿名内部类的语法。

此处是创建了一个类,实现 Runnable ,同时创建了类的实例,并且传给 Thread 的构造方法。

2.5 使用 Lambda 表达式(最简答、最推荐)

package thread;

public class ThreadDemo5 {
    public static void main(String[] args) {
        Thread thread = new Thread(() -> {
            System.out.println("hellohello");
        });
        thread.start();
    }
}

把任务用 Lambda 表达式来描述
直接把 Lambda 传给 Thread 构造方法。

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

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

相关文章

2000-2020年迪博上市公司内部控制指数

2000-2020年迪博上市公司内部控制指数 1、时间:2000-2020年 2、指标包括: 证券代码、证券简称、辖区、证监会行业、申万行业、内部控制指数、报告期 3、指标解释: 上市公司内部控制指数是结合国内上市公司实施内部控制体系的现状&#x…

java——电商购物平台

1.java编译环境的创建,与所需要用到的插件 (1) 选择的编译器为2022版本的intellij idea 首先新建一个空项目 同时,创建完之后,我们点击 文件 -> 项目结构 进入项目结构,点击项目,选择好你想要的jdk版本,若没有,可以在idea中下载,这里我使用openjdk-19, 点击模…

Python适合0基础菜鸟学吗

前言 经常有小伙伴问:Python适合0基础初学编程的人学吗?今天我们就来从Python的功能和特性方面看一下,Python是否能让新人快速上手。 1、非常适合。我觉得刚开始学编程,负担越少越好,应该尽快能做出东西来。刚开始学…

day02 linux常用命令

day02 linux 第一章 Linux常用命令 第一节 进程相关命令 1. 查看进程状态 1.1 命令的使用 ps命令是用于查看进程状态的命令,它常和e参数(对应单词entire,表示全部。具体指显示系统中全部的进程信息。),以及f参数(对应单词full-formate&a…

Node.js 入门教程 13 在 Node.js 中从命令行接收输入

Node.js 入门教程 Node.js官方入门教程 Node.js中文网 本文仅用于学习记录,不存在任何商业用途,如侵删 文章目录Node.js 入门教程13 在 Node.js 中从命令行接收输入13 在 Node.js 中从命令行接收输入 如何使 Node.js CLI 程序具有交互性? 从…

卡塔尔世界杯--程序员的诗和远方

💗wei_shuo的个人主页 💫wei_shuo的学习社区 🌐Hello World ! 卡塔尔世界杯–程序员的诗和远方 2022年卡塔尔世界杯(FIFA World Cup Qatar 2022)第二十二届世界杯足球赛,历史上首次在卡塔尔和中…

【学习笔记44】JavaScript的事件传播

JavaScript的事件传播一、事件传播1、事件传播的说明2、阻止事件传播二、目标冒泡捕获1、冒泡2、捕获三、事件委托1、事件委托的说明2、为什么要用事件委托四、阻止默认事件1、方法一2、方法二一、事件传播 在触发子元素的事件时, 会将行为传播给父级的同类型事件触发了子元素的…

机器学习1综述

文章目录一、综述学习环境:二、机器学习方法的分类1、监督学习;2、非监督学习;3、半监督学习;4、增强学习;三、机器学习方法分类2、批量学习(离线学习)Batch Learing;3、参数学习&am…

二叉树的递归问题

目录 一、相同的树 二、另一棵树的子树 三、翻转二叉树 四、平衡二叉树 五、对称二叉树 一、相同的树 给你两棵二叉树的根节点 p 和 q ,编写一个函数来检验这两棵树是否相同。 如果两个树在结构上相同,并且节点具有相同的值,则认为它们是…

【毕业设计-课程设计】-超声波测距

资源链接在文章最后,订阅查看获取全部内容及资料,如需可私信提供硬件。 目 录 1 绪论 2 1.1 项目研究背景及意义 2 2 总体设计方案及论证 2 2.1 总体方案设计 2 3 硬件实现及单元电路设计 3 3.1 主控制模块 3 3.2 电源设计 4 3.3 超声波测试模块 4 3.3.1 超声波的特性 5 3.3…

【Python】顺序、条件、循环语句

文章目录一. 顺序语句二. 条件语句1. 什么是条件语句2. 缩进和代码块3. 空语句 pass4. 练习三. 循环语句1. while 循环2. for 循环一. 顺序语句 默认情况下,Python 的代码执行顺序,是从上到下依次执行的: 执行结果一定为 “123”&#xff0…

【工具门户】Backstage配置使用PostgreSQL(三)

先决条件 If the database is not hosted on the same server as the Backstage app, the PostgreSQL port needs to be accessible (the default is 5432 or 5433) PostgreSQL数据库默认端口为5432或5433,如果数据库与Backstage应用不在同一台机器上,需开放PostgreSQL端口…

MyBatis框架一二级缓存含代码演示

目录 1.什么是缓存? 2. Mybatis的一级缓存 2.1实验一: 2.2实验二: 3.Mybatis的二级缓存 3.1 二级缓存需要配置才可以使用: 3.2 实验开始!! 4.总结 1.什么是缓存? 缓存就是数据交换的缓冲区(称作Cache),当某一…

学习Python中turtle模块的基本用法(2:基本绘图函数测试)

个人感觉turtle模块中的绘图函数是按人手拿着画笔一笔一画地画图的思路定义的,这与C#中的GDI函数、html5中canvas的绘图函数及Tkinter中Canvas的绘图函数的定义思路存在差异,但也能完成后面绝大部分的绘图功能(目前看到的turtle文章及帮助文档…

安装OpenGL

提示错误信息: (base) C:\Users\Tina\PycharmProjects\FunnyToys-main>conda install opengl Collecting package metadata (current_repodata.json): done Solving environment: failed with initial frozen solve. Retrying with flexible solve. Collecting…

python 栈空间不足异常 Process finished with exit code: -1073741571

问题现象 在pycharm使用debug模式调试代码时,异常退出,且错误码为-1073741571。除了错误码外,并没有看到其它报错。 分析 查阅资料: Process finished with exit code -1073741571 (0xC00000FD) when trying to implement ab…

AxureRP9的新特性介绍和技巧分享

AxureRP自去年8月第一个测试版本发布以来,已经一年多了,官方版本已经发布了近半年,但这个版本的用户声誉是褒贬不一的。许多用户反馈了他们对新版本的喜欢和肯定,但一些老用户仍然不愿意接受它,甚至保持抵制。 根据我…

【Hack The Box】linux练习-- Tabby

HTB 学习笔记 【Hack The Box】linux练习-- Tabby 🔥系列专栏:Hack The Box 🎉欢迎关注🔎点赞👍收藏⭐️留言📝 📆首发时间:🌴2022年11月22日🌴 &#x1f36…

【数据结构】基础:二叉树

【数据结构】基础:二叉树基础 摘要:本文将会介绍二叉树的基础内容,首先引入树的概念,了解树的基本概念与性质,再对二叉树的概念和性质进行分析,最后对其方法进行实现,最重要的是理解对于二叉树方…

世界65个国家贸易开放度数据 2005-2019年

一、数据介绍 数据名称:UNtrade数据库 数据年份:2005-2019年 数据范围:世界65个国家 数据来源:各地方统计局 部分数据如下: 二、参考文献 用途:研究人民币实际汇率与贸易差额之间的关系等。 [1]卢向…