济南市住建厅官方网站wordpress 插件 游戏

张小明 2026/3/2 14:45:51
济南市住建厅官方网站,wordpress 插件 游戏,策划方案范文,wordpress改版权文章目录Ⅰ. 创建线程的方式方式一#xff1a;继承 Thread 类#xff0c;重写 run()方式二#xff1a;实现 Runnable 接口#xff0c;重写 run()#xff0c;然后构造 Thread 进行传参方式三#xff1a;匿名内部类继承 Thread#xff0c;重写 run()方式四#xff1a;匿名…文章目录Ⅰ. 创建线程的方式方式一继承 Thread 类重写 run()方式二实现 Runnable 接口重写 run()然后构造 Thread 进行传参方式三匿名内部类继承 Thread重写 run()方式四匿名内部类实现 Runnable重写 run()方式五lambda 表达式创建 Thread 对象推荐⭐⭐⭐注意事项️使用 jconsole 程序观察线程Ⅱ. Thread 类及常见方法Ⅲ. 线程的状态与生命周期Ⅳ. 线程安全一、线程不安全的原因二、synchronized 关键字**① 修饰实例方法**② **修饰静态方法**③ **修饰代码块**推荐⭐⭐⭐synchronized 是可重入锁三、编译器优化问题① 内存可见性问题 -- volatile② Java内存模型 -- JMM③ 指令重排序Ⅰ. 创建线程的方式方式一继承Thread类重写run()/** * 创建线程方式一继承Thread类重写run() */classMyThreadextendsThread{Overridepublicvoidrun(){// ...}}publicclassdemo1{publicstaticvoidmain(String[]args){MyThreadtnewMyThread();t.start();}}方式二实现Runnable接口重写run()然后构造Thread进行传参/** * 创建线程方式二实现Runnable接口重写run()然后传给Thread */classMyRunnableimplementsRunnable{Overridepublicvoidrun(){// ...}}publicclassdemo2{publicstaticvoidmain(String[]args){// 传给Thread同时也可以给线程命名ThreadtnewThread(newMyRunnable(),MyThread);t.start();}}方式三匿名内部类继承Thread重写run()/** * 创建线程方式三匿名内部类继承Thread重写run() */publicclassdemo3{publicstaticvoidmain(String[]args){ThreadtnewThread(){publicvoidrun(){// ...}};t.start();}}方式四匿名内部类实现Runnable重写run()/** * 创建线程方式四匿名内部类实现Runnable重写run() */publicclassdemo4{publicstaticvoidmain(String[]args){RunnablemyrunnablenewRunnable(){Overridepublicvoidrun(){// ...}};ThreadtnewThread(myrunnable);t.start();}}方式五lambda表达式创建Thread对象推荐⭐⭐⭐/** * 创建线程方式五lambda表达式创建Thread对象顺便命名 */publicclassdemo5{publicstaticvoidmain(String[]args){ThreadtnewThread(()-{// ...},MyThread);t.start();}}注意事项继承Thread类直接使用this就表示当前线程对象的引用。实现Runnable接口this表示的是MyRunnable的引用需要使用Thread.currentThread()来获取当前线程对象。️使用jconsole程序观察线程在jdk的bin目录中有一个jconsole程序打开然后连接到对应的java程序就能看到对应的程序信息比如内存、线程等情况如下图所示Ⅱ.Thread类及常见方法方法名返回类型功能描述Thread()void构造一个新线程但不与任何Runnable对象关联。线程不会自动启动需要调用start()方法来启动线程Thread(Runnable target)void构造一个新线程并与指定的Runnable对象关联。Thread(Runnable target, String name)void构造一个新线程并与指定的Runnable对象关联同时设置线程的名称。Thread(String name)void构造一个新线程不与任何Runnable对象关联但设置线程的名称。static Thread currentThread()Thread返回当前正在执行的线程对象void start()void启动线程使线程进入就绪状态等待调度器调度后执行run()方法。 如果线程已经启动再次调用start()会抛出IllegalThreadStateException。void run()void线程的入口点通常需要重写以实现线程的具体逻辑。如果线程是通过Thread(Runnable)构造的则会调用Runnable的run()方法。如果不重写该方法默认为空实现。void join()void等待当前线程终止。调用该方法的线程会阻塞直到被调用join()的线程执行完毕。如果线程已经终止则立即返回。void join(long millis)void等待当前线程终止最多等待指定的毫秒数。如果线程在指定时间内结束则调用该方法的线程会继续执行。如果线程在指定时间内未结束则抛出InterruptedException。void join(long millis, int nanos)void等待当前线程终止最多等待指定的毫秒数和纳秒数。精确控制等待时间如果线程在指定时间内结束则调用该方法的线程会继续执行。下面三个中断相关的方法可以看看表格后面的注意事项void interrupt()void中断线程。如果线程正在休眠或阻塞不仅会设置中断标志为true还会抛出InterruptedException如果线程正在运行则只会设置中断标志为true。boolean isInterrupted()boolean检查线程是否被中断如果线程被中断了则返回true否则返回false。不设置中断标志。static boolean interrupted()boolean检查当前线程是否被中断如果当前线程被中断了则返回true并清除中断状态即设置中断标志为false。void sleep(long millis)void使当前线程暂停执行指定的毫秒数。调用该方法的线程会进入休眠状态不会占用 CPU 资源。如果线程在休眠期间被中断会抛出InterruptedException。void sleep(long millis, int nanos)void使当前线程暂停执行指定的毫秒数和纳秒数。精确控制线程的休眠时间。如果线程在休眠期间被中断会抛出InterruptedException。void yield()void暂停当前线程让其他具有相同优先级的线程运行。线程调度器会重新调度线程但不保证其他线程一定会运行。void setPriority(int priority)void设置线程的优先级优先级范围为 1最低到 10最高默认为 5。优先级高的线程可能会获得更多 CPU 时间。int getPriority()int获取线程的优先级返回线程的优先级值。void setName(String name)void设置线程的名称便于调试和监控。String getName()String获取线程的名称返回线程的名称字符串。void setDaemon(boolean on)void设置线程为守护线程或用户线程。守护线程在所有用户线程结束后自动退出。boolean isDaemon()boolean检查线程是否为守护线程如果是守护线程返回true。State getState()State获取线程的状态返回线程的当前状态如新建、运行、阻塞等。boolean isAlive()boolean检查线程是否处于活动状态如果线程已经启动且尚未终止返回true。void setUncaughtExceptionHandler(UncaughtExceptionHandler eh)void设置线程的未捕获异常处理器用于处理线程中未捕获的异常。UncaughtExceptionHandler getUncaughtExceptionHandler()UncaughtExceptionHandler获取线程的未捕获异常处理器返回设置的异常处理器对象。static void dumpStack()void打印当前线程的堆栈跟踪通常用于调试。注意事项run()只是注册了线程要做的动作start()才是真的启动线程。关于中断线程interrupt()方法将中断标志设为true表示 “我希望你停下来了”而是否停下来取决于程序员的代码逻辑不一定会真的中断只是希望中断在匿名内部类或者lambda表达式中要判断是否被中断有两种方式Thread.interrupted()Thread.currentThread().isInterrupted()更推荐这种方式因为保持中断标志不变有助于上层逻辑知道这个线程是否被中断过。通常interrupt()的是休眠或者阻塞的线程则会抛出InterruptedException异常此时捕获异常后可以在异常中处理一些需要收尾的业务而不要直接抛出RuntimeException等异常来终止进程这样子是不合理的如下面代码所示publicstaticvoidmain(String[]args)throwsInterruptedException{ThreadtnewThread(()-{// 还没被打断则进行循环while(Thread.currentThread().isInterrupted()false){System.out.println(Thread.currentThread().getName());try{Thread.sleep(1000);}catch(InterruptedExceptione){// 此时最好恢复中断标志因为 sleep 抛出异常时会清除中断状态Thread.currentThread().interrupt();// 处理可能剩余的业务而不至于直接退出导致业务完成一半// ...break;}}});t.start();System.out.println(main thread, 3秒后中断子线程);Thread.sleep(3000);t.interrupt();}有时我们需要等待一个线程完成它的工作后才能进行自己的下一步工作。例如张三只有等李四转账成功才能决定是否存钱这时我们需要join()来明确等待线程的结束在张三的线程中调用李四.join()即可保证在李四之后进行存钱操作JVM只有在一个进程的所有非后台线程结束后才会结束运行。Ⅲ. 线程的状态与生命周期线程的状态是枚举类型Thread.State如下所示状态名英文名描述NEW新建线程对象已创建但还没调用start()RUNNABLE可运行线程已启动等待CPU调度执行run()方法BLOCKED阻塞线程因等待锁资源而暂停执行WAITING等待线程无限期地等待另一个线程的唤醒例如调用了wait()、join()TIMED_WAITING计时等待线程在等待一个特定的时间后被唤醒如sleep(long)、join(long)、wait(long)TERMINATED终止线程已完成执行或异常退出我们可以通过Thread.getState()来获取当前进程在某个时刻的状态如下所示publicclassdemo{publicstaticvoidmain(String[]args)throwsInterruptedException{// 打印所有状态for(Thread.Statestate:Thread.State.values()){System.out.println(state);}System.out.println(-----------);// 打印 t 线程某个时刻的状态ThreadtnewThread(()-{for(inti0;i5;i){try{Thread.sleep(1000);}catch(InterruptedExceptione){thrownewRuntimeException(e);}}});System.out.println(t.getState() t.isAlive());t.start();System.out.println(t.getState() t.isAlive());t.join();System.out.println(t.getState() t.isAlive());}}// 运行结果NEW RUNNABLE BLOCKED WAITING TIMED_WAITING TERMINATED-----------NEWfalseRUNNABLEtrueTERMINATEDfalseⅣ. 线程安全一、线程不安全的原因线程的调度执行是随机的抢占式调度这是线程不安全的根本原因多个线程同时修改同一个变量修改变量的操作不是原子性的比如count并不是原子操作。注意java中对于内置类型的读取和赋值是原子性的内存可见性、指令重排序问题这两个问题通常用volatile来解决但是volatile并不保证原子性二、synchronized关键字进入synchronized修饰的代码块相当于加锁退出synchronized修饰的代码块相当于解锁实际上synchronized底层不只是加锁还有锁升级等机制具体可以看多线程进阶的笔记① 修饰实例方法publicsynchronizedvoiddoSomething(){// 临界区代码}锁对象是this当前实例。多个线程调用同一个对象的该方法时会串行执行。②修饰静态方法publicstaticsynchronizedvoiddoSomethingStatic(){// 临界区代码}锁对象是类名.class。多个线程访问同一个类的静态同步方法也会被串行化。③修饰代码块推荐⭐⭐⭐privatefinalObjectlocknewObject();// 自定义锁对象publicvoiddoSomething(){synchronized(lockObject){// 临界区代码}}锁对象除了内置类型以外可以是任意类型的对象但通常不能是String、Integer、Boolean等常量对象因为多个类、多个线程可能锁的是同一个对象锁对象最好声明为private。因为如果锁对象是public的别的类也能访问和同步这个对象可能破坏原有的同步逻辑。此外为了保证锁对象在多线程可见性和稳定性上的安全性通过要给锁对象加上final关键字修饰。举个例子给你一把锁如果别人偷偷换了一把新的你以为门锁住了其实别人可以从另一把锁进来这就是 “非 final locker” 导致的线程安全崩溃。synchronized是可重入锁在java中synchronized同步块对同一条线程来说是可重入的即不会出现自己把自己锁死的问题。可重入锁指的是同一个线程 可以多次获得同一个锁不会发生死锁。每进入一层synchronized或调用一层锁方法锁的持有计数lock count 1退出对应的一层lock count - 1。只有当计数变为0锁才真正释放。如下面代码所示for(inti0;i50000;i){// 连续两次锁同一个对象在java中并不会出现死锁只会被看做是一层加锁synchronized(locker){// lock count1synchronized(locker){// lock count1count;}// lock count-1}// lock count-1}注意如果是一个线程进行多层获取同一个锁只有锁计数count为0才会释放该锁对象如下所示ObjectlockernewObject();synchronized(locker){// 1synchronized(locker){// 1synchronized(locker){// 1synchronized(locker){// 1// 此时锁计数 4线程持有 locker 的锁 4 次}// -1计数 3}// -1计数 2}// -1计数 1}// -1计数 0真正释放锁三、编译器优化问题在java程序编译期间用javac将.java文件编译成.class文件这并不涉及到优化问题但后续JIT编译器Just-In-Time Compiler会在JVM运行期间将热点代码即被JVM判定为值得优化的代码编译为本地机器码提升性能这就形成了一些优化比如内联函数、指令重排序、内存不可见、锁优化。这些优化实际上是很有必要的因为很多编程新手对于程序的性能把握并不好所以编译器这一层就多干了很多活来提高程序的效率相当于提高了程序的效率下限。但这些优化又无形带来了一些编程时候的bug为了防止这些bug我们可以使用内存屏障语义的关键字来避免如下所示volatile阻止指令重排序 保证变量对其他线程的可见性synchronized包含获取/释放锁的内存屏障final构造后不可变构造安全不能被重排① 内存可见性问题 –volatile以下面代码为例在t2输入非零之后正常情况应该是t1就结束循环了但程序却停不下来t1一直在循环之中这是为什么❓❓❓publicclassdemo1{privatestaticintcount0;publicstaticvoidmain(String[]args){Threadt1newThread(()-{while(count0){// do something}System.out.println(t1循环结束);});Threadt2newThread(()-{ScannerscnewScanner(System.in);countsc.nextInt();System.out.println(t2结束);});t1.start();t2.start();}}这就是之前提到的编译器优化带来的问题编译器会把while(count 0)认为是热点代码因为这是一个循环会大量重复地访问count所以编译器会将原本存放在内存中的count复制到CPU的寄存器或者缓存中然后在CPU中访问这可以大大提高访问速度因为CPU速度可是要比内存访问速度快上几千倍不止的但正是因为这个问题t2修改的count还是那个存放在内存中的count而此时t1那边跑的是CPU中的count看不到内存那边已经修改了所以就会一直判断while(count 0)是成功的导致了程序错误此时只需要在count前面加上volatile进行修饰强制让编译器访问内存的那份count即可解决这个优化带来的问题但同时速度就会降低② Java内存模型 –JMMJVM定义了一种Java内存模型Java Memory ModelJMM来屏蔽掉各种硬件和操作系统的内存访问差异以实现让Java程序在各种平台下都能达到一致的内存访问效果。在此之前C/C直接使用物理硬件和操作系统的内存模型因此会由于不同平台下的内存模型的差异导致程序在一套平台上并发完全正常而在另一套平台上并发访问经常出错。在多线程中CPU和编译器会出于性能考虑进行缓存优化每个线程有自己的工作内存指令重排序编译器或CPU会乱序执行某些语句这些优化可能导致一个线程修改的变量另一个线程看不到从而引发 “明明已经赋值却读取到旧值” 等并发bug而JMM就是为了解决这些问题而生。JMM的主要目标是定义程序中各个变量的访问规则即在JVM中将变量存储到内存和从内存中取出变量这样的底层细节。此处的变量包括实例字段、静态字段和构成数组对象的元素但不包括局部变量和方法参数因为后两者是线程私有的不会被线程共享。JMM规定了所有的变量都存储在 “主内存” 中。每个线程还有自己的 “工作内存”线程的 “工作内存” 中保存了被该线程使用到的变量的 “主内存” 副本拷贝线程对变量的所有操作如读取、赋值等都必须在 “工作内存” 进行而不能直接读写 “主内存” 中的变量。所以不同的线程之间也无法直接访问对方 “工作内存” 中的变量线程间变量值的传递均需要通过 “主内存” 来完成。“主内存” 和 “工作内存” 的描述如下表所示位置描述主内存Main Memory所有共享变量都在这里工作内存Working Memory每个线程自己的变量副本缓存看起来很复杂其实很简单主内存 就是我们平常所说的主存而 工作内存 实际上是CPU中的缓存和寄存器而JMM这一套规则实际上和我们上面讲解volatile时候解释的内存可见性是一个道理的只不过用 “工作内存” 这个术语来涵盖了我们提到的CPU中的缓存或者寄存器即原始数据都是存放在 “主内存”然后根据JMM优化会放到 “工作内存” 中执行速度会大大提高但就会存在 “主内存” 和 “工作内存” 数据不一致的情况此时就要通过volatile来解决如果只关注操作系统或者硬件来说根本就没有 “主内存”、“工作内存” 的说法虽然java官方给的 “工作内存” 这个概念让人很晕实际上就是指CPU中的缓存和寄存器甚至指以后可能更新的缓存技术但它的目的实际上是要让java程序员不用去关心底层是什么结构让 “工作内存” 来直接代指这些缓存或者寄存器甚至以后可能更新出来的技术只需要让程序员知道这是 “工作内存” 的概念即可③ 指令重排序简单的说指令重排序就是编译器或CPU为了优化性能改变了语句执行顺序导致和原先的程序逻辑不一致的情况为了避免这种情况同样是要使用volatile、synchronized、final等手段建立有序性屏障
版权声明:本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!

跨境建站平台西安网app

Mac微信功能增强插件完整使用教程:提升办公效率的终极方案 【免费下载链接】WeChatExtension-ForMac Mac微信功能拓展/微信插件/微信小助手(A plugin for Mac WeChat) 项目地址: https://gitcode.com/gh_mirrors/we/WeChatExtension-ForMac 还在为Mac版微信功…

张小明 2026/2/27 22:43:48 网站建设

intitle:做网站建设局属于什么单位

SenseVoice极速语音识别:70ms颠覆传统,多语言智能转录新标杆 【免费下载链接】SenseVoice Multilingual Voice Understanding Model 项目地址: https://gitcode.com/gh_mirrors/se/SenseVoice 还在为语音转文字等待时间过长而烦恼?Sen…

张小明 2026/2/28 6:58:51 网站建设

网站建设核心系统3322网建站

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容: 开发一个Ubuntu下载方式对比工具,功能:1. 同时启动多种下载方式(HTTP/FTP/BT/CDN) 2. 实时监测并记录下载速度 3. 生成可视化对比图表 4. 提供下载策略建议 …

张小明 2025/12/31 4:14:22 网站建设

手机app制作网站模板十大ps培训机构

终极解决!ComfyUI-Manager节点安装失败?4步快速修复完整指南 🛠️ 【免费下载链接】ComfyUI-Manager 项目地址: https://gitcode.com/gh_mirrors/co/ComfyUI-Manager 近期众多ComfyUI用户反映:在安装自定义节点时遭遇Comf…

张小明 2026/1/7 15:19:00 网站建设

阳江网站网站建设app运营成本估算

引言:峰会核心命题 ——AI 普及时代,IP 变现的关键是 “找准生态位” 而非 “追逐流量”2025 年 11 月 22 日 - 25 日,由创客匠人主办的 “全球创始人 IPAI 万人高峰论坛” 在厦门圆满落幕。这场汇聚近万名创业者、投资人及行业领袖的盛会&am…

张小明 2025/12/30 19:20:59 网站建设

网页游戏网站斗地主网站源码如何优化

摘 要 近年来家政行业发展迅猛,社会上家政服务需求旺盛,大量的社会人员涌入家政服务行业,家政行业作为朝阳产业,发展潜力巨大,有助于改善民生,提高社会就业率。在家政行业快速发展的社会背景下&#xff0c…

张小明 2025/12/30 15:18:24 网站建设