【Java高级特性】java学习之旅35-多线程

图信号处理中的多尺度分析:图小波变换与图傅里叶变换的对比与应用 本文深入探讨了图信号处理中的多尺度分析方法,重点对比了图小波变换(GWT)与图傅里叶变换(GFT)的技术特点与应用场景。通过分析图的拓扑结构,GWT展现出强大的局部洞察力,适用于异常检测和社区发现;而GFT则擅长全局频率分析,适合趋势分析和信号去噪。文章结合实战案例,为读者提供了方法选型指南和前沿进展,帮助开发者在生物信息学、社交网络分析等领域高效应用这些技术。 阅读详情

什么是线程,什么是进程?

进程:进行中的程序,系统中的最小执行单元,有独立的运行空间和内存空间

线程:进程中的最小执行单元,每一个进程至少包含一个主线程。

什么是并发,什么是并行?

并发:多个线程争抢系统资源,交替执行,单核单线程cpu即可执行。

并行:多个线程同时执行,互不影响,必须要在多线程CPU上才能执行。

实现多线程的根本目的:

根本目的是压榨系统资源,可以一定程度上的提高任务执行效率。

常用方法:

  1. 设置线程的名字:setName(String name)
  2. 获取线程的名字:Thread类中的getName(); Thread.currentThread.getName()
  3. 启动线程:start()

如何创建一个线程(4种方式):

  1. 自定义线程类继承Thread类
/**
* 1. 创建一个自定义的类继承Thread
* 2. 重写run()方法,方法内编写线程任务
* 3. 创建自定义线程的对象,执行start()方法
*/
public class MyThread01 extends Thread {
    
    @Override
    public void run(){
        long startTime = System.out.currentTimeMillis();
        for(int i = 1; i <= 100; i++){
            System.out.println(Thread.currentThread().getName() + ":" + i);
        }
        long endTime = System.currentTimeMillis();
        System.out.println(Thread.currentThread().getName() + "用时" + (endTime - startTime));
    }
}

public static void test1(){
    //使用对象去点run方法也可以实现,但是与线程无关了
    //public synchronized(同步)  void start() 使用线程的开始方法start()会默认去找run方法
    MyThread01 thread01 = new MyThread01();
    thread01.setName("线程1");
    MyThread01 thread02 = new MyThread01();
    thread02.setName("线程2");
    //这里如果统计时间,发现两个线程的时间比按次序打印的时间还要慢
    //这是因为打印方法的out是static修饰的全局共用这一个,还有println方法是加上了 synchronized同步锁使得一次只有
    //一个线程访问进来
    thread01.start();
    thread02.strat();
}
  1. 自定义线程类实现Runnable接口
/**
* 1. 创建一个自定义的类实现Runnable接口
* 2. 重写run()方法
* 3. 创建自定义线程类的对象
* 4. 创建Thread对象,使用自定义线程类的对象作为有参构造的参数
* 5. 执行Thread对象的start()方法
* 注意:Runnable是函数式的接口,可以使用lambda表达式做实现
*/

//第一种实现方式
public class MyThread02 implements Runnable{
    
    @Override
    public void run(){
        long startTime = System.currentTimeMillis();
        for(int i = 1; i <= 100; i++){
            System.out.println(Thread.currentThread().getName() + ":" + i);
        }
        long endTime = System.currentTimeMillis();
        System.out.println(Thread.currentThread().getName() + "用时" + (endTime - startTime));
    }
}

public static void test2(){
    MyThread02 run = new MyThread02();
    
    Thread thread1 = new Thread(run);
    thread1.setName("线程1");
    thread1.start();
    
    Thrad thread2 = new Thread(run);
    thread2.setName("线程2");
    thread2.start();
}

//第二种实现方式
Runnable run = () -> {
    for (int i = 1; i <= 100; i++){
        System.out.println(Thread.currentThread().getName() + ":" + i);
    }
};

Thread thread = new Thread(run);
thread.start();

3.自定义线程类实现Callable接口(jdk1.5+,可以抛出异常,可以有返回值)

/**
* 1. 创建一个自定义的类实现callable接口
* 2. 重写call()方法
* 3. 创建自定义线程的对象
* 4. 创建FutureTask类的 对象,把自定义线程对象作为构造方法的参数。
* 5. 创建Thread类对象,把FutureTask类的对象作为构造方法的参数
* 6. 调用Thread对象的start()方法;
*/
public class MyThread03 implements Callable<Long> {
    @Override
    public Long call() throws Exception {
        long startTime = System.currentTimeMillis();
        for (int i = 1; i <= 100; i++){
            System.out.println(Thread.currentThread().getName() + ":" + i);
        }
        long endTime = System.currentTimeMillis();
        return endTime - startTime;
    }
}

private static void test4() {
    //三层包装,第一步创建实现了Callable接口的实现类对象
    MyThread03 myThread03 = new MyThread03();
    //创建FutureTask对象将实现类对象作为参数放入FutureTask对象中
    FutureTask<Long> futureTask = new FutureTask<>(myThread03);
    //创建线程对象,将FutureTask对象作为参数,FutureTask对象继承了Runnable所以多态可以放入其中
    Thread thread = new Thread(futureTask);
    
    thread.start();
    //使用该接口创建线程的好处
    // 1. 可以获得返回值
    // 2. 如果线程中有异常可以抛出
    try{
        //通过FutureTask对象可以获得call()方法的返回值
        Long result = futureTask.get();
        System.out.println(result);
    } catch (InterruptedException | ExecutionException e) {
        e.printStackTrace();
    }
}
  1. 使用线程池创建线程
/**
* 1. 创建一个指定容量的线程池
* 2. 创建一个单例的线程池
* 3. 创建一个缓存型的线程池
*/

//使用固定大小的线程池
//可以理解为我们往线程池里面提交线程,但是线程池固定了大小,一次只会跑3个线程,当线程结束时,别的线程 才会进来
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);
//往线程池中放入6个线程
for(int i = 1; i <= 6; i++) {
    //将线程提交到线程池中
    fixedThreadPool.submit(new Runnable() {
        @Override
        public void run(){
            for (int i = 0; i <= 100; i++){
                 System.out.println(Thread.currentThread().getName() + ":" + i);
            }
        }
    }
}

//创建一个单例的线程池
//无论往线程池中丢入多少的数据,线程池一次只会执行一条线程
ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
for(int i = 1; i <= 3; i++){
    singleThreadExecutor.submit(() -> {
    for (int j = 1; j <= 100; j++){
        System.out.println(Thread.currentThread().getName() + ":" + j);
    });
}

//创建一个缓存型的线程池
//程序根据系统自身来定,能跑多少个线程就跑多少个线程
ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
for(int i = 1; i <= 10000; i++){
    cachedThreadPool.submit(() -> {
        for (int j = 1; j <= 100; j++){
            System.out.println(Thread.currentThread().getName() + ":" + j);
        }
    }
}

线程的分类:

  1. 主线程:一般是主方法的线程
  2. 子线程:一般情况下都是用户创建的线程
  3. 守护线程:给主线程和子线程提供底层的技术支持,如果主线程或者子线程死亡,守护线程也没有存活的价值

线程的声明周期:

  1. 创建状态:创建出Thread的实例
  2. 就绪状态:线程对象执行start()方法之后,运行状态释放系统资源也会进入
  3. 运行状态: 线程获取到系统资源
  4. 等待用户输入、线程休眠都会进入阻塞
  5. 死亡状态: 线程执行完毕、手动停止线程
//线程的生命周期
private static void test1(){
    Thread thread = new Thread(() -> {
        for (int i = 1; i <= 100; i++){
            System.out.println(i);
        }
    });
    //-------------到此是创建状态-----------------
    thread.start();
    //-------------线程进入就绪状态---------------
    //线程在系统内部获取cpu资源
    //-------------进入运行状态-------------------
    //任务执行完毕,或者手动停止任务
    //-------------进入死亡状态-------------------
}

线程的调度:

  1. 调度的策略
  1. 分时调度
  2. 抢占式调度
  3. java使用的是抢占式的方式
  1. 设置线程的优先级 setPriority(int level):
//MIN_PRIORITY = 1;最小是1
//NORM_PRIORITY = 5;默认是5
//MAX_PRIORITY = 10;最大是10

Runnable runnable = () -> {
    for(int i = 1; i <= 100; i++){
        System.out.println(Thread.currentThread().getName() + ":" + i);
    }
};

Thread thread1 = new Thread(runnable);
Thread thread2 = new Thread(runnable);

//设置线程1和线程2的优先级,线程2先跑完,1才会跑
thread1.setPriority(1);
thread2.setPriority(10);

thread1.start();
thread2.start();
  1. 线程的休眠 Thread.sleep(long time):
//这里注意的是sleep()方法是静态的方法,可以通过Thread类直接调用,不需要创建对象再调用
Runnbale runnable = () -> {
    for(int i = 1; i <= 100; i++){
        if(i == 50){
            try{
            //通过Thread类直接调用sleep方法,睡眠10秒
                Thread.sleep(10000);
            } catch(InterruptedException e){
                e.printStackTrace();
            }
        }
        System.out.println(Thread.currentThread().getName + ":" + i);
    }
};

Thread thread1 = new Thread(runnable);
Thread thread2 = new Thread(runnbale);

thread1.start();
thread2.strat();
  1. 线程的礼让 Thread.yield():
//当前线程释放系统资源,进入就绪状态,和其他线程再次争抢资源,这里注意这次礼让只会释放cpu资源并不是直接让另一个线程进来,而是再次争抢。
Thread thread1 = new  Thread(() -> {
    for (int i = 1; i <= 100; i++) {
        if (i == 30) {
        //当线程1打印到30的时候会释放cpu资源,然后再次争抢
            Thread.yield();
        }
        System.out.println(Thread.currentThread().getName() + ":" + i);
    }
});

Thread thread2 = new Thread(() -> {
	for (int i = 1; i <= 100; i++) {
		System.out.println(Thread.currentThread().getName() + ":" + i);
	}
});

thread1.start();
thread2.start();
  1. 线程的加入 join():
//主线程可以实现子线程的加入(使用子线程的对象调用join()方法),子线程加入之后,不再和主线程交替执行,主线程会进入阻塞一直到子线程执行完毕

Thread thread1 = new Thread(() -> {
    for(int i = 1; i <= 100; i++){
        System.out.println(Thread.currentThread().getName() + ":" + i);
    }
});

thread1.start();

for(int i = 1; i <= 100; i ++){
    if (i == 30) {
    //当主线程执行到等于30时会让线程1加入进来,这里线程会执行完毕才会出来
        try{
            thread1.join();
        } catch (IntertupttedException e) {
            e.printStackTrace();
        }
    }
    System.out.println(Thread.currentThread().getName() + ":" + i);
}

线程锁的概念

  1. 对象互斥锁
    1. 当使用多个线程要同时访问一个变量或对象时,如果这些线程中既有读又有写操作时,就会导致变量值或对象的状态出现混乱,从而导致程序异常
    2. 当一个线程拿到锁的时候,其他线程不能获得锁;获得锁的线程可以执行被锁住的代码;当这个线程 执行完毕这块代码后,释放锁,此时其他线程和他一起争抢锁
    3. 如何实现互斥锁:(在java中采用同步机制来实现互斥锁 )
      1. 同步方法
      2. 同步代码块
    4. 常用的锁:
      1. 对象锁:任意对象,如:Object lock = new Object();获得this
      2. 类锁:类的Class对象,如TicketsThread01.class

使用:

  1. 使用同步方法:
public class TicketsThread02 extends Thread {
	
	//线程操作的对象,一定要设置为静态的,共用的代码
	private static int ticketCount = 1000;
	
	private static int count = 0;
	
	//synchronized修饰的静态同步方法
	public static synchronized void buyTicket() {
		if (ticketCount > 0) {
			count++;
			System.out.println(Thread.currentThread().getName() + "抢了第"+ count +"张票!");
			ticketCount--;
			System.out.println("还剩" + ticketCount + "张票!");
		}
	}
	
	//run方法中调用方法
	@Override
	public void run() {
		while (true) {
			buyTicket();
		}
	}

}
  1. 同步代码块实现同步:
public class TicketsThread03 extends Thread {
	
	private static int ticketCount = 1000;
	
	private static int count = 0;
	
	//设置共用静态对象
	private static Object lock = new Object();
	
	@Override
	public void run() {
		while (true) {
		    //同步对象锁
		    //如果实现两个线程和其他的一个线程锁不同,只需要创建不同的对象放入其中
			synchronized(lock) {
				if (ticketCount > 0) {
					count++;
					System.out.println(Thread.currentThread().getName() + "抢了第"+ count +"张票!");
					ticketCount--;
					System.out.println("还剩" + ticketCount + "张票!");
				}
			}
		}
	}
}

这里注意一点:(如果我们使用Runnable这个借口就可以使用this关键词)

public class TicketsThread04 implements Runnable {
	
	private static int ticketCount = 1000;
	
	private static int count = 0;
	
	@Override
	public void run() {
		while (true) {
			synchronized(this) {
				if (ticketCount > 0) {
					count++;
					System.out.println(Thread.currentThread().getName() + "抢了第"+ count +"张票!");
					ticketCount--;
					System.out.println("还剩" + ticketCount + "张票!");
				}
			}
		}
	}

}

//在主线程中创建一个runnable的对象
public static void main(String[] args) {
    TicketsThread04 run = new TicketsThread04();
}
死锁:(由于两个线程同时需要对方的锁,导致无法释放自己的锁,所以导致程序一直这样不执行)
public static void main(String[] args) {
    Object lock1 = new Object();
    Object lock2 = new Object();
    
    new Thread(new Runnable() {
        @Override
        public void run() {
            synchronized (lock1) {
                Sysyem.out.println("我是线程1,我拿到lock1");
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                sychronized (lock2) {
                System.out.prinyln("我是线程1,我拿到了lock2");
                }
            }
        }
    }).start();
    
    new Thread(new Runnable() {
        @Override
        public void run() {
            synchronized (lock2) {
                System.out.println("我是线程2,我拿到了lock2");
                try {
                    Thread.sleep(300);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (lock1) {
                    System.out.pirntln("我是线程2, 我拿到了lock1");
                }
            }
        }
    }).start();
}

线程通信:

线程的等待和通知机制

使用的方法:
1.wait():当前使用锁的线程进入阻塞状态

Thread thread1 = new Thread(new Runnable() {
    @Override
    public void run() {
        synchronized(lock) {
            for (int i = 0; i <= 100; i++) {
                System.out.println(Thread.currentThread().getName() + ":" + i);
                if (i == 50) {
                    try {
                        //使用wait()会使当前对象释放锁,并且进入阻塞状态
                        lock.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
}

Thread thread1 = new Thread(new Runnable() {
    @Override
    public void run() {
        synchronized(lock) {
            for (int i = 0; i <= 50; i++) {
                System.out.println(Thread.currentThread().getName() + ":" + i);
            }
            //使用notify()会通知被该锁阻塞的可以执行了
            lock.notify();
            
            //使用notityAll()方法会让多个被阻塞的对象都可以回到就绪状态,但是第一个被锁住的对象会先执行,阻塞相当于是一个队列
        }
    }
}
27、物联网中的量子密钥分发:安全通信新范式 本文探讨了物联网(IoT)快速发展所带来的安全挑战,并提出量子密钥分发(QKD)作为应对新兴威胁的新范式。文章详细介绍了QKD的基础原理、BB84协议的实现流程以及其在物联网中的应用前景,同时强调了安全专业人员提升技能、制定标准化指南以及跨学科合作的重要性。通过利用量子力学特性,QKD能够提供更高的通信安全性,抵御量子计算等未来威胁,为物联网的安全发展提供保障。 阅读详情

相关推荐

《Ventoy 制作系统安装 U 盘的具体步骤》

然后您可以在电脑的磁盘管理中对 U 盘进行快速格式化,选择 FAT32 或 NTFS 文件系统。至此,Ventoy 系统安装 U 盘就制作完成了。您可以在需要安装系统的电脑上,从 U 盘启动,然后选择相应的系统镜像进行安装。安装完成后,将您需要的操作系统镜像文件(如 Windows、Linux 等的 ISO 格式镜像)复制到 U 盘的根目录。在安装程序中,选择您插入的 U 盘设备,确保选择正确,以免误操作。2. 确认选择的 U 盘盘符正确,防止误操作导致其他磁盘数据丢失。点击“安装”按钮,等待安装完成。

jiyiwangluokeji的博客 2665

JAVA之旅(三十五)——完结篇,终于把JAVA写完了,真感概呐!

JAVA之旅(三十五)——完结篇,终于把JAVA写完了,真感概呐! 这篇博文只是用来水经验的,写这个系列是因为我自己的java本身也不是特别好,所以重温了一下,但是手比较痒于是就写出了这三十多篇博客了,而且收到的好评也不错,于是就一直坚持了下来,非常感谢各位小伙伴哦! JAVA之旅合集 JAVA之旅(一)——基本常识,JAVA概念,开发工具,关键字/标识符,变量/常量,进制/进制转换,运算符

刘桂林的博客 2万+

nRF52382低功耗蓝牙应用开发之入门教程-软件烧录

准备工作在上一篇文章讲过了,这里就讲讲nRFgo studio的使用 硬件准备: J-link:2线 供电:3.3V 如下图打开nRFgo studio界面介绍, 2、如果J-link正常,如下图 3、如果蓝牙芯片正常 4、烧录过程,如果蓝牙芯片之前有烧录过程序,需先点擦除,再点烧录 5、烧录代码路劲,例如 F:\nRF\SDK\nRF5_SDK_15.2.0_...

LinQiPing233的博客 1945

35岁开始学习Java之前世今生

一、前言                 我,35岁,一个大龄青年。工作十年多了,一直从事编程,较多使用的是Delphi语言。那是我十年前的一个选择,当时Delphi还很火,业界流传着一句话:“聪明的程序员选择Delphi",那个时候确实很喜欢Delphi,通过它我领悟了面向对象思想。最喜欢这门语言的原因是它的开发环境带着源代码,让我有机会去学习大师们的编程思路;另外一个原因是那个时候网络上De

35岁学习Java 6558

欧姆龙PLC的FinsTCP协议

三个流行的PLC: PLC 通讯协议 默认IP和端口 区别 西门子S7-1200 S7 192.168.1.201 :102 2次验证(正常连接后,第一次发不断开,第二次发断开) 三菱Q系列 MC 192.168.1.250 :4096 不验证(正常连接后,怎么发都不断开) 欧姆龙CJ-2M系列 FinsTCP 192.168.1.14 :9600 1次验证(正常连接后,第一次发断开) ...

周林的博客 1万+

【Python机器学习】主成分分析(PCA):高维数据的“瘦身术“

主成分分析(PCA)的历史可以追溯到1901年,当时Karl Pearson首次提出了这个概念。在计算机还不存在的年代,PCA是一个纯粹的数学构想,用来简化多变量数据的分析。几十年后,当计算机出现时,PCA成为了数据分析中最早实现的算法之一。从那时起,超过一个世纪的发展中,PCA一直保持着其核心的理论框架和实用价值,这本身就是对这个方法深刻科学性的证明。在现代深度学习时代,许多人可能会认为PCA已经过时了。但事实恰好相反。

nmdbbzcl的博客 981

Java高级特性 编程及实战

目录 序言 前言 第一章 集合框架和泛型 ··························································································· 1 任务1 查询标题 ·························································...

JavaDarren的博客 2547

OpenOCD入门到精通:第20章 Target 子系统源码分析

摘要:本章深入分析OpenOCD Target子系统的核心实现机制。重点包括:1) 通过target_type虚函数表实现多架构抽象,支持ARM、RISC-V等30+种目标;2) ARM ADIv5协议栈实现,包含DAP/AP核心数据结构和访问机制;3) 分层架构设计,从调试接口层到传输层的完整调用链路。系统采用面向对象思想,统一管理目标状态、寄存器缓存、断点/观察点等调试要素,为上层提供标准化的调试操作接口。

从事嵌入式linux android驱动开发,拥有全栈能力 176

Java中高级岗面试为何越来越难,java高级特性面试题

作为过来人,小编是整理了很多进阶架构视频资料、面试文档以及PDF的学习资料,针对上面一套系统大纲小编也有对应的相关进阶架构视频资料《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!,可以扫码获取!!(备注:Java)**[外链图片转存中…(img-Xmb2EcRz-1713841016979)]作为过来人,小编是整理了很多进阶架构视频资料、面试文档以及PDF的学习资料,针对上面一套系统大纲小编也有对应的相关进阶架构视频资料。

2301_82243139的博客 989

基于Simulink的电动汽车电池管理系统热管理优化仿真

电动汽车电池管理系统(Battery Management System, BMS)中的热管理是确保电池性能、安全性和寿命的关键环节。温度过高或过低都会显著影响电池的工作效率和寿命,因此需要对电池组进行精确的热管理。基于MATLAB/Simulink的仿真平台可以用于建模和优化电池热管理系统,包括热分布预测、冷却策略设计以及热平衡控制等。本项目旨在构建一个完整的电动汽车电池热管理优化仿真模型,并通过仿真验证系统的性能。

xiaoheshang_123的博客 461

第五节_PySide6基本窗口控件_主窗口和标签

本文介绍了PySide6中主窗口和标签控件的使用。主要内容包括: 窗口控件分类: QWidget是基础窗口部件,可作为独立窗口或子部件 QMainWindow提供标准应用程序框架,包含菜单栏、工具栏等 QDialog用于对话框,支持模态交互 主窗口创建: 演示了如何创建QMainWindow子类 实现了窗口居中、设置图标、状态栏等功能 提供了窗口几何信息的获取方法 QLabel标签控件: 继承自QFrame类 用于显示文本或图像 文章通过代码示例详细说明了主窗口的创建和使用方法,包括位置控制、图标设置等常见

su桥木的博客 1021

Spring AI + GPT-5.5 + Ollama 配置教程:Base URL、超时与流式调用

由于不同 Spring AI、Spring Boot 小版本之间仍可能存在差异,创建项目时应检查 Spring Initializr、Spring AI BOM 和官方兼容矩阵,不要直接复制旧教程中的 Starter 名称和版本号。多人项目最好隔离不同客户端,并在脱敏前提下记录最终 URL、状态码、请求耗时、请求 ID 和模型 ID。Spring AI 接入模型 API,至少要同时确认 Starter、Base URL、请求路径、API Key、模型 ID、连接超时、读取超时和流式客户端这 8 项。

2601_95893075的博客 219

在 SAP 中,寄售业务(Consignment)与管道业务(Pipeline)都属于“物料先到、发票后到”的特殊采购模式,但两者的库存形态、物权转移时点、结算触发条件、系统配置完全不同

SAP中寄售业务与管道业务均属"先货后票"采购模式,但存在本质差异。寄售业务(如手机芯片)采用实物库存管理(标记"K"),物权在领用时转移,通过411K/201K移动类型触发负债;管道业务(如蒸汽)无实物库存,采用261P等移动类型直接消耗并生成应付。系统配置上,寄售需K类信息记录及GR收货,管道需P类信息记录且免GR。两者均通过MRKO汇总结算,但寄售按领用量计费,管道按提取量实时计费。核心区别在于库存形态与物权转移时点。

金牌架构师 555

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

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

qq_38468358的博客 328

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

【JVM】对象内存布局

HotSpot JVM 中,Java 对象内存布局由对象头(12字节,含Mark Word与压缩Klass Pointer)、实例数据及对齐填充构成,总大小为8字节倍数。对象头支持锁状态动态复用,指针压缩使引用仅4字节,但堆超32GB时失效。实例字段按类型优先级重排序以减少间隙,最小对象大小为16字节。通过JOL工具可精准验证布局,理解锁机制、GC、伪共享等底层行为。

2301_79732484的博客 148

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

Java EE 进阶:8.MyBatis 操作数据库(入门)(第一弹)

Java EE 进阶:8.MyBatis 操作数据库(入门)(第一弹)

要努力去发光,而不是被照亮~ 114

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

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

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

BADAO_LIUMANG_QIZHI的博客 192

LeetCode Hot 100 二叉树专题(二)3 题(Java)

本篇文章共 3 题:543. 二叉树的直径、102. 二叉树的层序遍历、108. 将有序数组转换为二叉搜索树。 每道题都统一按「① 题目分析 & 解题思路 → ② 常见解法(附代码)及讲解 → ③ 知识点总结」的顺序组织;代码使用 Java 编写,节点定义沿用 LeetCode 默认的 TreeNode。

2401_88612756的博客 360

Decorator

TaskDecorator 是异步场景下"跨线程传递上下文"的标准方案,主要用于传递 MDC、用户信息、数据源路由等上下文数据,核心价值是让异步任务的日志链路不中断、业务上下文不丢失。TaskDecorator 是 Spring 提供的一个钩子接口,用于在异步任务执行前对 Runnable 进行包装,常用于跨线程传递上下文。如果你在项目中遇到具体的异步上下文传递问题,可以把代码贴出来,我帮你给出最合适的 Decorator 方案 👍。✅ 核心能力:在线程切换时,把"父线程的上下文"搬到"子线程"

wlwork66的博客 102

数据库乐观锁深度解析:MySQL、PostgreSQL 实战 + Spring Boot 集成指南

Oracle 提供了ORA_ROWSCN伪列(System Change Number),记录最后修改行的 SCN,类似 PostgreSQL 的xmin。实践中通常仍使用 version 字段方案,逻辑与 MySQL 完全相同。-- Oracle:通过 ORA_ROWSCN 实现乐观锁-- 更新时比对 SCN// 自定义注解// AOP 切面@Aspect@Component@Slf4jtry {

yjc_1111的专栏 394

JDK 下载安装:装完 Java 提示「不是内部或外部命令」?环境变量没配

JDK 是写 Java 程序必须装的东西。它包含运行 Java 的虚拟机(JRE)和编译 Java 的编译器(javac)——装了它,能跑、.java文件能编译成可执行程序。免费,学习和小规模生产都不花钱。

科小怪的博客 623

C++ 多态详解:作用、原理与实战用法

多态是C++面向对象的核心特性,通过虚函数实现运行期动态绑定,使同一接口在不同对象上表现出不同行为。其核心作用包括统一接口、提升可扩展性、降低耦合、支持运行时分派与批量处理。实现依赖虚函数表(vtable)和虚指针(vptr),需注意虚析构函数、对象切片等陷阱。相比编译期多态(模板),运行期多态灵活性高但有调用开销。合理结合两者,可兼顾代码的灵活性与性能,是构建可扩展、低耦合系统的关键。

2402_85743155的博客 376

java框架大全

java框架大全

qq_39326137的博客 183

Java 多态 学习笔记

多态是面向对象编程的重要特性,指同一操作作用于不同对象时产生不同行为。其核心在于“父类引用指向子类对象”,结合方法重写实现运行时动态绑定。多态使代码更灵活、可扩展,如用Person p = new Student();统一处理各类人员注册,无需修改调用逻辑。但多态无法直接调用子类特有方法,需通过instanceof判断并强制转换。编译时看左边(类型),运行时看右边(实际对象),实现解耦与维护便利。

AA_AA114514的博客 337

SecureRandom做随机源,这个Java随机字符串工具类有3个方法

本文分享一款JDK17环境下的Java随机字符串工具类,内置3个开箱即用的方法,全部采用SecureRandom加密安全随机源,不存在弱随机、可预测、取模偏差等问题。工具类支持默认62字符集随机串、纯数字随机串、自定义字符集随机串三种生成模式,支持Unicode码点级别的字符集处理,兼容Emoji等增补字符,边界处理严格,异常信息明确,适合验证码、邀请码、盐值、随机口令、短链码等场景,源码可直接复制使用。

Java后端 | AI智能体应用实战派 | 电脑技能行家 294

Java实现批量线段相交检测(跨积判定+扫描线优化与踩坑复盘)

【代码】Java实现批量线段相交检测(跨积判定+扫描线优化与踩坑复盘)

m0_64476639的博客 317
上一篇: 【Java高级特性】java学习之旅34-序列化与反序列化
下一篇: 【Java高级特性】java学习之旅36-网络编程
JeffHan^_^
博客等级 码龄7年 1万+粉丝 134原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JeffHan^_^

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值