javase-thread-210201-01

编程语言的未来走向:趋势、挑战与机遇 同时,鼓励他们接触和掌握一些专业领域的开发工具和技术框架,比如Web开发中的JavaScript、React.js,数据分析的Python(Pandas, NumPy, Matplotlib等),以及人工智能和机器学习领域的TensorFlow、PyTorch等。当前,全球范围内正积极推动编程教育的普及化,从儿童启蒙阶段到高等教育阶段,乃至终身学习的过程中,如何优化编程语言的教学方法、提高教学质量,并将其广泛应用于不同领域,是教育者与政策制定者面临的重大课题。未来,编程语言的多样化和包容性将会继续加强。 阅读详情

javase-thread-210201-01

  • 简介
  • 创建线程
  • 练习
  • 静态代理模式

简介

  • 线程实现
  • 线程状态
  • 线程同步
  • 线程通信问题

操作系统中运行的程序就是进程,一个进程可以有多个线程

程序是指令和数据的有序集合,其本身没有任何运行的含义,是一个静态的概念

进程是执行程序的一次执行过程,它是一个动态的概念。是系统资源分配的单位

通常在一个进程中可以包含若干个线程,一个进程中至少有一个线程(主线程),不然没有意义。线程是CPU调度和执行的单位。

注:很多线程是模拟出来的,真正的多线程是指由多个cpu,即多核,如服务器。如果是模拟出来的多线程,即在一个cpu的情况下,在同一个时间点,cpu只能执行一个代码,因为切换很快,所以就有同时执行的错局。

  • 线程就是独立的执行路径
  • 在程序运行时,即使没有自己创建的线程,后台也会有多个线程,如主线程,gc线程
  • main()称主线程,为系统的入口,用于执行整个程序
  • 在一个进程中,如果开辟了多个线程,线程的运行由调度器安排调度,调度器是与操作系统紧密相关的,先后顺序是不能人为干预的
  • 对同一份资源进行操作时,会存在资源抢夺问题,需要加入并发控制
  • 线程会带来额外的开销,如cpu调度时间,并发控制开销
  • 每个线程在自己的工作内存交互,内存控制不当会造成数据不一致

创建线程

1.Thread(类)
//继承Thread类
/*
	步骤:
		1.自定义线程类,继承Thread类
		2.重写run()方法,编写线程执行体
		3.创建线程对象,调用start()方法启动线程
*/

//线程开启不一定立即执行,由cpu调度执行
package bgy210310;

public class Demo01 extends Thread{

    // 重写 run() 方法
    @Override
    public void run(){
        for (int i = 0; i < 100; i++) {

            // 修改线程名称
            Thread.currentThread().setName("线程一");

            System.out.println("当前线程为" + Thread.currentThread().getName());

            // 线程睡眠
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {

        // 创建线程对象
        Demo01 demo01 = new Demo01();
        // 开启线程
        demo01.start();


        // 主线程
        for (int i = 0; i < 100; i++) {

            // 修改线程名称
            Thread.currentThread().setName("主线程");

            System.out.println("当前线程为" + Thread.currentThread().getName());
        }
    }
}

2.Runnable(接口)
/*
    1.定义Demo02类实现Runnable接口
    2.实现run()方法
    3.创建线程对象,调用start()方法,启动线程
*/

public class Demo02 implements Runnable{

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {

            // 修改线程名称
            Thread.currentThread().setName("线程一");

            System.out.println("当前线程为" + Thread.currentThread().getName());

            // 线程睡眠
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
//        Demo02 demo02 = new Demo02();
//        Thread thread = new Thread(demo02);       // 代理模式
//        thread.start();

//        Thread thread = new Thread(new Demo02());
//        thread.start();

        // 创建线程并启动
        new Thread(new Demo02()).start();

        // 主线程
        for (int i = 0; i < 100; i++) {

            // 修改线程名称
            Thread.currentThread().setName("主线程");

            System.out.println("当前线程为" + Thread.currentThread().getName());
        }
    }
}

3.Callable(接口)
/*
    1.实现 Callable 接口
    2.重写call方法,,需要抛出异常,并且需要一个返回值
    3.创建目标对象
    4.创建执行服务     ExecutorService service = Executors.newFixedThreadPool();
    5.提交执行        Future<Boolean> r = service.submit();
    6.获取结果        boolean rs = r.get();
    7.关闭服务        service.shutdown();
 */

public class Demo03 implements Callable<Boolean> {
    @Override
    public Boolean call() throws Exception {
        for (int i = 0; i < 100; i++) {
            System.out.println("当前线程为" + Thread.currentThread().getName());

            // 线程睡眠
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        return true;
    }

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        // 创建目标对象
        Demo03 demo03_01 = new Demo03();
        Demo03 demo03_02 = new Demo03();

        // 创建执行服务
        // 参数是 你想有几个线程,就来几个,我目前是2个线程,,就是2
        ExecutorService service = Executors.newFixedThreadPool(2);

        // 提交执行
        Future<Boolean> r1 = service.submit(demo03_01);
        Future<Boolean> r2 = service.submit(demo03_02);

        // 获取结果
        boolean rs1 = r1.get();
        boolean rs2 = r2.get();

        // 关闭服务
        service.shutdown();
    }
}

练习

买票问题
/*
	出现问题:
		多个线程操作同一个资源的情况下,出现了线程不安全
*/

public class Demo04 implements Runnable{
    // 目前有30张票
    public int numTicket = 30;

    @Override
    public void run() {
        while (true){
            if(numTicket <= 0){
                System.out.println("票以售空");
                break;
            }

            // 模拟买票延时
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            System.out.println(Thread.currentThread().getName() + "拿到第" + numTicket-- + "张票");
        }
    }

    public static void main(String[] args) {
        Demo04 demo04 = new Demo04();
        new Thread(demo04,"小明").start();
        new Thread(demo04,"王刚").start();
        new Thread(demo04,"黄牛").start();
    }
}

龟兔赛跑
public class Demo05 implements Runnable{
    private int distance = 100;
    private String winner;

    @Override
    public void run() {
        for (int i = distance; i >= 0; i--) {

            // 模拟兔子休息
            if(Thread.currentThread().getName().equals("兔子")){
                try {
                    Thread.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

            // 判断比赛是否结束
            boolean flag = isOver(i);
            if (flag){
                break;
            }

            System.out.println(Thread.currentThread().getName() + "还剩" + i + "米");
        }
    }

    // 判断是否跑完路程
    public boolean isOver(int distance){
        // 已经存在获胜者
        if (winner != null){
            return true;
        }
        if (distance <= 0){
            winner = Thread.currentThread().getName();
            System.out.println(winner + "获胜");
            return true;
        }

        return false;
    }

    public static void main(String[] args) {
        Demo05 demo05 = new Demo05();
        new Thread(demo05,"兔子").start();
        new Thread(demo05,"乌龟").start();
    }
}

静态代理模式

package bgy210310;

/*
    1.真实对象和代理对象都要实现同一个接口
    2.代理对象要代理真实角色
    
    优点:
    	1.代理对象可以做很多真实对象做不了的事情
    	2.真实对象专注做自己的事情
 */

interface Wedding{
    void happyWedding();
}

// 真实角色,,,谁要结婚
class You implements Wedding{
    @Override
    public void happyWedding() {
        System.out.println("白光一要结婚了,很高心");
    }
}

// 代理角色,,,表示婚庆公司,来个你安排婚礼,帮助你结婚
class WeddingCompany implements Wedding{

    // 真实角色
    private Wedding target;

    public WeddingCompany(Wedding target){
        this.target = target;
    }

    @Override
    public void happyWedding() {
        before();
        this.target.happyWedding();     // 真实角色
        after();
    }

    private void after() {
        System.out.println("结婚之后,婚庆公司拿钱,撤散现场");
    }

    private void before() {
        System.out.println("结婚之前,婚庆公司策划婚礼,布置现场");
    }

}

public class Demo06 {
    public static void main(String[] args) {
        WeddingCompany weddingCompany = new WeddingCompany(new You());
        weddingCompany.happyWedding();
    }
}
private void after() {
    System.out.println("结婚之后,婚庆公司拿钱,撤散现场");
}

private void before() {
    System.out.println("结婚之前,婚庆公司策划婚礼,布置现场");
}

}

public class Demo06 {
public static void main(String[] args) {
WeddingCompany weddingCompany = new WeddingCompany(new You());
weddingCompany.happyWedding();
}
}


STM32实现任意角度移相全桥PWM STM32实现任意角度移相全桥PWM,最小分辨率0.5度,频率占空比课任意调节 本文重点在于如何产生任意角度的移相, 两个定时器工作于主从模式,从模式为Gate mode,用第一个定时器触发第二个来实现延时移相 阅读详情

相关推荐

C++游戏开发实战:从零构建局域网联机对战系统(附完整代码解析)

本文详细介绍了如何使用C++开发局域网联机对战游戏系统,涵盖从环境搭建到实战代码解析的全过程。重点讲解了Winsock库的应用、Socket通信原理、服务端与客户端开发技巧,以及性能优化和安全防护方案,帮助开发者快速掌握C++游戏开发的核心技术。

weixin_42524945的博客 445

javase-io-210509-02

javase-io-210509-02 File FIle Fiel 1、 File类和四大家族没有关系,所以FIle类不能完成对文件的读和写 2、 FIle对象代表 文件和目录路径名的抽象表示形式 C:\bgy 这是一个文件 C:\bgy\bgy.txt 这也是一个文件 Demo01.java import java.io.File; import java.io.IOException; public class Demo01 { public static v

白光一的博客 286

rk3568 rockit编译测试

编译rockit不能使用SDK默认编译kernel的交叉编译,需要采用编译buildroot的,而编译buildroot的编译器SDK并没有存放,需要编译过buildroot之后才可以用。命令参数相关解析可查阅代码,这里提醒一下-l参数,这是程序运行计数,默认是100,时间很短,基本上显示画面一闪而过,一度以为是程序哪里出问题了,改用-l 1000,画面显示时间加长。此处跳过系统,单领出来编译。rockit组件包在4.10版本需要手动编译,奈何我的版本怎么都编译不了,后来改用5.10版本才编译通过。

zfenggo的博客 4197

javase-collection-210623-02

javase-collection-210623-02 HashTable Properties HasTableTest01.java package bgy_hashtable01; import java.util.Hashtable; import java.util.Map; /* 1. HashTable中的方法都带有synchronized关键字,是线程安全的 线程安全目前有其它方案,HashTable对线程的处理导致效率较低,所以使用较少 2

白光一的博客 275

硬件作品3----STM32F103RCT6最小系统板MCU配置

电路未调试成功,目前刚打板,后续需要补充或者改版另行注明。

weixin_58364194的博客 5561

电路研究9.4——合宙Air780EP的LuatOS、CSDK跟标准AT

 C-SDK、AT指令、LuatOS

esmember的博客 1116

javase-collection-210619-01

javase-collection-210619-01 Collection------remove() 在集合中使用remove()方法,会使得集合的结构发生改变,如果此时迭代器还是原来的那个,会报错 例子:CollectionTest02.java 1. 如果使用集合的remove()方法进行删除,要通知迭代器更新,否则报错 2. 或者使用迭代器的remove()方法进行删除 CollectionTest01.java package bgy_test_2161901; import j

白光一的博客 253

告别手动复制粘贴!用R语言脚本批量抓取TCMSP中药靶点基因(附完整代码)

本文介绍如何使用R语言脚本自动化抓取TCMSP数据库中的中药靶点基因数据,告别手动复制粘贴的低效操作。通过详细的代码示例和参数设置,帮助研究人员快速获取并过滤符合药代动力学标准的中药成分及其靶点基因,大幅提升研究效率。特别适合生物信息学和中药现代化研究领域的从业者。

weixin_26950847的博客 263

javase-collection-210408-01

javase-collection-210408-01 什么是集合 集合继承图 Collection常用方法 集合遍历迭代 contains方法 什么是集合 集合就是一个容器,数组就是一个集合,它可以来容纳其他类型的数据 集合不能直接存储基本类型的数据,另外集合也不能直接存储java对象, 集合当中存储的都是java对象的内存地址,或者说是集合中存储的引用 注:集合在java中本身是一个容器,是一个对象,集合中任何时候储存的都是引用 在java中每一个不同的集合,底层会对应不同的数据结构。往不

白光一的博客 250

r语言svr模型_R语言初探强化学习中的马尔可夫模型

强化学习大家这几年应该不陌生,从AlphaGo到AlphaZero让大家见识到了强化学习的力量。我们今天给大家介绍一个在强化学习中核心思维马尔可夫决策过程(MDP)。马尔科夫决策过程是基于马尔科夫论的随机动态系统的最优决策过程。它是马尔科夫过程与确定性的动态规划相结合的产物,故又称马尔科夫型随机动态规划,属于运筹学中数学规划的一个分支。今天我们给大家介绍下马尔可夫决策过程中用到一些算法以...

weixin_28994357的博客 1111

SAP ABAP 如何实现物料主数据接口的增量传输机制?

如何实现物料主数据接口的增量传输机制?我在各客户系统中看到了五花八门的实现方式,即使是 IBM 实施的开发质量也并没有保证。其实这是一个很简单的问题,下面以物料主数据接口为例子,介绍 SAP 中更改文档对象的接口数据增量传输机制。

SAP李斌,本人承诺所有原创文章均不使用任何AI生成技术,请大家放心阅读。 1316

javase-io-210510-02

javase-io-210510-02 IO+Properties 读取配置文件 读取配置文件 IO + Properties Properties 是一个Map集合,key和value都是String类型 经常变的数据,可以单独写到一个文件中,让程序动态读取 那么我们就需要配置文件了,java规范中要求,属性的配置文件建议以 .properties 结尾,,但不是必须是 Demo01.java package com.bgy02; import java.io.FileNotFoundE

白光一的博客 240

OD图 arcgis曲线制作插件 od图曲线 路径图曲线制作插件 航线图曲线制作插件

在ArcGIS 10.2 中导入节点数据,打开插件,选择输入起始节点和目标节点的节点文件Point,以Name字段(地名)为连接线的起始字段和目标字段,(Input Table File)选择连接关系表格SDLine.csv,(Origin Column 和 Destination Column)为起始节点和目标节点,(Output Path)为输出路径,应选择.gdb数据库路径,否则容易报错,(Chord Coefficient)为连线的曲率,数值越大,曲率越高。运行环境:ArcGIS10.2。...

JData_Engineer的博客 2670

javase-collection-210623-01

javase-collection-HashMap-210623-01 HashMap HashMapTest01.java package bgy_hashmap01; /* 1. HashMap底层用的是 哈希表/散列表 的数据结构 1)哈希表是一个数组和单向链表的结合体 2)它是一个一维数组,数组中每一个元素是一个单向链表 3)数组:查询效率高,随机增删效率低 4)单向链表:随机增删效率高,查询效率低 1)

白光一的博客 234

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

javase-collection-210620-01

javase-collection-210620-01 List ArrayList ListTest01.java package bgy_list_01; import java.util.*; /* 1. List 特点: 有序可重复 1)有序:List集合中的元素有下标 从0开始,以1递增 2)可重复:存一个‘bgy’,还能再存一个‘bgy’ 2. List是Collection的子接口

白光一的博客 230

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

javase-collection-210624-01

javase-collection-210624-01 TreeSet Collections工具类 TreeSetTest01.java package bgy_treeset01; /* 1. TreeSet 集合底层实际上是一个TreeMap 2. TreeMap集合底层是一个二叉树 3. 放到TreeSet集合中的元素,等同于放到TreeMap集合key部分了 4. TreeSet集合 无序不可重复,可以按照元素的大小顺序自动排序,

白光一的博客 228

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

javase-io-210508-01

javase-io-210508-01 什么是IO IO分类 Java中IO四个部落 需要知道 1、什么是IO流 ​ I:Input ​ O:Output ​ 通过IO完成对硬盘文件的读和写 2、IO分类 1. 按照 流 的方式进行分类 以内存为参照物 往内存中去,叫做输入(Input),也叫读(Read) 从内存中出来,叫做输出(Output),也叫做写(Write) 2. 按照读取数据方式进行分类 一、 按照 字节方式

白光一的博客 217

javase-annotation-210710-01

javase-annotation-210710-01 注解解释 元注解 Retention源码 Target源码 注解解释 1) 注解 也叫注释,Annotation 2) 注解Annotation是一种引用数据类型,编译之后也是生成xxx.class文件 3) 自定义注解,语法如下: [修饰符列表] @interface 注解类型名{ } 4) 注解如何使用?在哪里使用? 注解使用语法格式: @注解类型名 注解可以出现在类上,属性上,方法上,变量上等

白光一的博客 211

javase-annotation-210710-02

javase-annotation-210710-02 注解中可以用的属性类型 反射获取类上的注解 反射获取类中方法上的注解 注解实例 注解中可以用的属性类型 MyAnnotation0301.java package bgy_annotation_02; public @interface MyAnnotation0301 { /* 注解当中的属性可以是哪种类型 byte short int long float double bool

白光一的博客 209

javase-reflect-210625-01

javase-reflect-210625-01 反射的理解 反射机制有什么用? 通过java语言中的反射机制可以操作字节码文件 类似于黑客。(可以读和修改字节码文件) 通过反射机制可以操作代码片段(class文件) 反射机制的相关类的包 java.lang.reflect.*; 反射机制的相关的重要类 java.lang.Class 代表整个字节码,代表一个类型。 代表整个类 java.lang.reflect.Method 代表字节码中的方法字节码。 代表类中的方法 J...

白光一的博客 206

javase-collection-210621-01

javase-collection-210621-01 LinkedList Vector LinkedListTest01.java package bgy_linkedlist01; /* LinkedList 的数据结构是 双向链表 基础单元为节点node 每一个节点node都有两个属性: 1. 存储的数据 2. 下一个节点的内存地址 LinkedList集合底层也是有下标的 ArrayL

白光一的博客 201

javase-javabase-210126-02

javase-javabase-210126-02 JavaDoc Scanner对象 重载 可变参数 递归 Java内存 数组 Arrays类 JavaDoc @author 作者名 @version 版本号 @since 指明需要最早使用的jdk版本 @param 参数名 @return 返回值情况 @throws

白光一的博客 199

javase-io-210509-01

javase-io-210509-01 FileReader FileWriter 拷贝 BufferedReader InputStreamReader BufferedWriter DataOutputStream DataInputStream PrintStream FileReader ​ 文件字符输入流,只能读取普通文本 ​ 读取文本内容,比较方便,快捷 Demo01 import java.io.FileNotFoundException; import java.io.FileRead

白光一的博客 197

InnoDB 内存结构总览:Change Buffer、AHI 与 Log Buffer

本文系统梳理InnoDB内存结构中的ChangeBuffer、Adaptive Hash Index(AHI)与LogBuffer。ChangeBuffer缓存二级索引页不在内存时的变更,减少随机IO,仅在页加载时合并;聚簇索引修改立即执行,因数据本身不可延后。AHI基于高频等值查询自动构建哈希索引,加速定位,仅支持等值操作。LogBuffer为redo log内存缓冲,配合磁盘日志实现崩溃恢复。三者均服务于性能优化,其中ChangeBuffer与AHI共享BufferPool空间,而LogBuffer独立

bksczm的博客 285

V8 机制、手写核心函数与 TypeScript 类型体操

或固定初始化(如数组先定长、对象先给全字段)保持类型与形状稳定;这些都比"换框架"更基础。只能处理纯数据(丢函数、Date、RegExp、循环引用报错)。生产级深拷贝要处理:原始值短路、循环引用、V8(Chrome / Node 的 JS 引擎)不是"解释一行跑一行"那么简单,它用。图:V8 执行流程——解释执行 + 热点优化,优化失败会 Deopt 回退。JS 内存自动管理,但"自动"不等于"不会漏"。是"固定间隔最多执行一次"。手写 Promise 是"懂异步"的试金石。是"停下后才执行最后一次",

qq_38468358的博客 346

Spring Boot 数据源与 MyBatis(-Plus) 自定义配置详解

本文详解 Spring Boot 中单数据源环境下 HikariCP 与 MyBatis-Plus 的自定义配置。通过手动声明 SqlSessionFactory,实现下划线转驼峰、日志输出、一级缓存策略等精细化控制。结合 HikariCP 核心参数调优(如最大连接数、连接生命周期),确保高性能与稳定性。适用于仅需访问单一数据库的场景,避免多数据源复杂性,兼顾性能与可维护性。

BADAO_LIUMANG_QIZHI的博客 198
上一篇: javase-collection-210624-01
下一篇: javase-thread-210312-01
白光一
博客等级 码龄9年 0粉丝 174原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值