- 博客(16)
- 收藏
- 关注
原创 八、并发工具(下)
如果线程池中线程数为3,然后CyclicBarrier(2) 设置了2,那么如果下面的例子中task1跟task2循环执行3次,然后task1执行1秒,task2执行2秒,但是我们可以允许三个线程同时执行,然后就是task1 1秒 task2 2秒 task1 1秒,然后CyclicBarrier只能统计两个,所以我们统计的可能不是task1 跟 task2,可能是 task1 task1,因为执行时间不一样,所以可能导致结果有误差,所以建议设置成相同的,才能达到最佳效果。
2024-02-04 17:56:46
831
1
原创 七、并发工具(上)
在 QPS 量比较高的情况下,我们不可能说所有的访问都创建一个线程执行,这会导致内存占用过高,甚至有可能出现 out of memory另外也要考虑 cpu 核数,如果请求超过了cpu核数,那么有一部分线程就会收到限制,然后等cpu时间片结束会进行一个上下文切换,频繁的上下文也会影响性能。总和以上,我们可以引出线程池的概念,也就是结合前面的享元模式,创建一批线程,复用线程,既可以较少内存占用,又可以较少线程上下文切换。
2024-02-01 22:41:25
955
1
原创 五、无锁并发
为了实现多个线程对变量累加,如果一个线程就用base,多个线程就创建数组,每个线程对数组中自己独有的元素进行累加,最后把数组取和就行。
2024-01-26 19:41:17
882
1
原创 四、JMM
volatile 只能保证 有序性 和 可见性,但是不能保证原子性,不能解决指令交错。写屏障只能保证之后的读都是读取最新的结果,但是如果其他线程在当前线程写屏障写入主存的时候读取了旧值,这时候就不能保证了。有序性 只是保证了本线程内相关代码不被重排序,还是不能避免多个线程之间指令交错。
2024-01-24 22:02:16
833
1
原创 三、线程安全
wait()、notify()、 notifyAll() 方法都是属于Object 对象的方法,需要获取此对象的锁 之后才能够使用wait() 对象调用wait() 方法之后,线程会 Owner中释放锁,然后进入WaitSet中等待唤醒wait( time ) 对象调用带参数的wait()方法之后,线程会 Owner中释放锁,然后进入WaitSet中等待 指定时间,然后如果期间没有被唤醒,指定之间之后就会自动唤醒,然后进入EntryList再次尝试获取锁,竞争锁。
2024-01-21 18:50:31
1369
原创 二、Java线程
方法1 是把线程和任务合并在一起, 方法2 是把线程和任务分开了用Runnable 更容易与线程池等高级API 配合用 Runnable 让任务类脱离了Thread 继承体系,更灵活sleep 调用是进入等待阻塞状态, cpu时间片不会分配给阻塞状态的线程,需要等到他醒过来进入就绪状态。yield 调用是进入 就绪 状态, cpu 是会将时间片分配给就绪状态的线程, 也就是说如果没有其他线程,这时候yield 也就是没让出去。
2024-01-13 18:18:28
1067
1
原创 一、进程与线程
多线程可以让方法执行变为异步的(即不要巴巴干等着)比如说读取磁盘文件时,假设读取操作花费了5秒钟,如果没有线程调度机制,这5秒调用者什么都做不了,其代码都得暂停。注意:同步在多线程中还有另外一层意思,是让多个线程步调一致。从方法调用的角度来讲,如果。
2024-01-12 16:54:03
872
1
原创 七、运行期优化
一开始调用的是native本地的反射invoke方法,然后执行了15次达到一个阈值之后,会将本地的反射实现类修改成GenerateMethodAccessor1的新的反射实现类,这个实现类会在内部将反射调用转化成类名.方法名的方式调用,提高效率。总之就是发现热点代码,然后提高将其编译成机器码来提高效率。节省1900去查找成员变量的操作。阈值15是可以通过参数设定的。
2024-01-11 15:52:52
360
原创 六、类加载器
一、概述二、启动类加载器最顶层的加载类,由C++实现,负责加载 %JAVA_HOME%/lib ⽬录下的jar包和类或者或被 -Xbootclasspath 参数指定的路径中的所 有类。相关命令如下:了解一下就行三、扩展类加载器主要负责加载⽬录 %JRE_HOME%/lib/ext ⽬录下 的jar包和类,或被 java.ext.dirs 系统变量所指定的路径下的jar包。四、应用程序类加载器⾯向我们⽤户的加载器,负责加载当前应⽤classpath下 的所有jar包和
2024-01-10 20:40:54
554
原创 五、类加载阶段
加载class类到方法区,然后下面的链接和初始化都是为了初始化方法区class类的成员变量,链接是初始化常量池字符引用为真正引用,初始化是给_mirror赋值。就是执行类的构造方法的阶段,也就是执行()V 方法的阶段,虚拟机会保证类的【构造方法】的线程安全。这时候D只是C中的一个未解析的符号引用,虚拟机是不知道他是什么东西的,也不知道他的内存地址。例如:如果修改了类的class文件的魔数信息,就会验证不通过,报错。将常量池中的符号引用 解析 为直接引用。那么这时候D也不会被加载、解析初始化。
2024-01-10 20:40:03
351
原创 四、类文件 | 字节码 | 语法糖
第一个方法的访问标志值 为0x0001,也就是只有ACC_PUBLIC标志为真,名称索引值为0x0007,查代码清单6-2的常量池得方法 名为“”,描述符索引值为0x0008,对应常量为“()V”,属性表计数器attributes_count的值为 0x0001,表示此方法的属性表集合有1项属性,属性名称的索引值为0x0009,对应常量为“Code”,说明 此属性是方法的字节码描述。对于接口索引集合,入口的第一项u2类型的数据为接口计数器(interfaces_count),表示索引表 的容量。
2024-01-09 19:58:32
1190
原创 三、垃圾回收
清除只需要记录对应内存的起始地址,终结地址,然后存到一个空闲队列等待分配minor gc会引发stop the world(暂停其他用户的线程,垃圾回收线程执行完成之后恢复)如果发现当前放入的对象太大,在老年代完全足够,然后伊甸园完全不够的情况下,寿命没有到15,也会自动晋升,放到老年代中。如果一个线程出现了OutOfMemoryError,不会导致整个java进程的结束。
2024-01-05 21:26:52
927
原创 二、内存结构
Program Counter Register 程序计数器(寄存器)Java Virtual Machine Stacks(Java虚拟机栈)1、每个线程运行时所需要的内存, 称为虚拟机栈2、每个栈由多个栈帧(Frame)组成,对应着每次方法调用时所占用的内存3、每个线程只能由一个活动栈帧,对应着当前正在执行的那个方法问题辨析:1、垃圾回收是否涉及栈内存?答: 否,垃圾回收器只会回收堆内存中的内存占用,栈的空间执行完之后会弹出,出栈,所以不需要垃圾回收器回收2、栈内存分配越大越好吗?
2023-12-03 16:43:03
834
原创 牛客小白月赛80
2、接下来考虑用二分答案,二分的mid表示还留在学校最多人数的班级是mid,所以不能有超过mid的人数的班级存在,所以判断超过了mid的班级减去mid之后的超过人数总和能否等于k, 也就是 求出 所有班级人数 >= mid 的班级超过mid的部分的总和 跟k进行比较。3、只需要求出大于mid的班级人数之和 、 大于mid的班级数量,维护两个前缀和就可以实现,详细看代码。这里a[i]表示第i个班级的人数 ,如果小于k ,说明剩余的人达不到题目要求输出-1;
2023-10-28 01:32:41
42
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人