java线程图
A. java如何实现多线程绘图
首先,如果你只是要实现电子时钟,根本就不需要用到多线程。
如果你真的是要使用,就新建一个类,实现Runnable接口就是了。
如:
class MyThread1 implements Runnable{
public MyThread(){
}
public void run(){
}
}
使用的时候,就:
Thread myThread=new Thread(new MyThread());
myThread.start();
如果要画图,你就直接把组件通过构造方法传到MyThread中就是了
B. 再见了Future,图解JDK21虚拟线程的结构化并发
Java为我们提供了多种并发编程手段,本文将探讨一些关键概念和方法。首先,简要介绍基础方法,即使用Lambda表达式创建平台线程。然而,这种方法在大多数应用程序服务器中不被鼓励,因此转向更高级的解决方案,如Java的Futures。
JDK 5引入了Futures类,允许开发者将任务提交到线程池并返回结果。通过ExecutorService接口实现任务提交,它是一个用于管理任务执行的机制。然而,Futures存在一些问题,例如,使用Platform线程时,获取结果的操作会阻塞线程,这可能导致性能问题。
Java 21的虚拟线程(Virtual Threads)提供了改进,通过使用Virtual Threads,当使用future.get()方法阻塞线程时,底层的平台线程不会被阻塞。这解决了Futures中的一个关键问题。同时,使用CompletableFuture Pipelines也可以解决阻塞问题,但本文将重点介绍Virtual Threads的优势。
结构化并发的概念旨在更好地组织和管理任务执行。它强调了一个块(如方法或块)内启动的所有任务应在该块结束时终止。这样可以实现更清晰的代码结构和易于理解的执行顺序。Java 21中引入的StructuredTaskScope类试图提供更干净的结构化并发模型,它能够更好地处理任务之间的关系。
StructuredTaskScope类能够自动取消在任一任务失败时执行的后续任务,确保没有未完成的任务遗留。通过使用StructuredTaskScope创建的结构化任务范围,可以实现代码的模块化和一致性,提高开发效率。
本文示例展示了一个用例,其中两个任务可以并行运行,然后将结果合并到单个对象中返回。通过使用StructuredTaskScope.ShutdownOnFailure()方法,可以确保在任一任务失败时,其他任务自动被取消。这避免了等待时间过长或保留未明确终止的线程的问题。
在编写使用StructuredTaskScope的代码时,开发者需要确保任务能够正确处理取消期间设置的中断标志。任务应该检查并适当终止,以确保用例的响应性。总的来说,StructuredTaskScope和Virtual Threads共同提供了一种强大的并发编程方法,适用于将任务拆分为多个子任务的复杂用例。
C. 简速java语言中线程对象都有哪些状态,这些状态如何变化
线程的状态转换是线程控制的基础。线程状态总的可分为五大状态:分别是生、死、可运行、运行、等待/阻塞。用一个图来描述如下:
1、新状态:线程对象已经创建,还没有在其上调用start()方法。
2、可运行状态:当线程有资格运行,但调度程序还没有把它选定为运行线程时线程所处的状态。当start()方法调用时,线程首先进入可运行状态。在线程运行之后或者从阻塞、等待或睡眠状态回来后,也返回到可运行状态。
3、运行状态:线程调度程序从可运行池中选择一个线程作为当前线程时线程所处的状态。这也是线程进入运行状态的唯一一种方式。
4、等待/阻塞/睡眠状态:这是线程有资格运行时它所处的状态。实际上这个三状态组合为一种,其共同点是:线程仍旧是活的,但是当前没有条件运行。换句话说,它是可运行的,但是如果某件事件出现,他可能返回到可运行状态。
5、死亡态:当线程的run()方法完成时就认为它死去。这个线程对象也许是活的,但是,它已经不是一个单独执行的线程。线程一旦死亡,就不能复生。 如果在一个死去的线程上调用start()方法,会抛出java.lang.IllegalThreadStateException异常。
有关详细状态转换图可以参看本人的“Java多线程编程总结”中的图
二、阻止线程执行
对于线程的阻止,考虑一下三个方面,不考虑IO阻塞的情况:
睡眠;
等待;
因为需要一个对象的锁定而被阻塞。
1、睡眠
Thread.sleep(long millis)和Thread.sleep(long millis, int nanos)静态方法强制当前正在执行的线程休眠(暂停执行),以“减慢线程”。当线程睡眠时,它入睡在某个地方,在苏醒之前不会返回到可运行状态。当睡眠时间到期,则返回到可运行状态。
线程睡眠的原因:线程执行太快,或者需要强制进入下一轮,因为Java规范不保证合理的轮换。
睡眠的实现:调用静态方法。
try {
Thread.sleep(123);
} catch (InterruptedException e) {
e.printStackTrace();
}
睡眠的位置:为了让其他线程有机会执行,可以将Thread.sleep()的调用放线程run()之内。这样才能保证该线程执行过程中会睡眠。
例如,在前面的例子中,将一个耗时的操作改为睡眠,以减慢线程的执行。可以这么写:
public void run() {
for(int i = 0;i<5;i++){
// 很耗时的操作,用来减慢线程的执行
// for(long k= 0; k <100000000;k++);
try {
Thread.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace(); .
}
System.out.println(this.getName()+" :"+i);
}
}
D. java 线程池 工作队列是如何工作的
使用线程池的好处
1、降低资源消耗
可以重复利用已创建的线程降低线程创建和销毁造成的消耗。
2、提高响应速度
当任务到达时,任务可以不需要等到线程创建就能立即执行。
3、提高线程的可管理性
线程是稀缺资源,如果无限制地创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一分配、调优和监控
线程池的工作原理
首先我们看下当一个新的任务提交到线程池之后,线程池是如何处理的
1、线程池判断核心线程池里的线程是否都在执行任务。如果不是,则创建一个新的工作线程来执行任务。如果核心线程池里的线程都在执行任务,则执行第二步。
2、线程池判断工作队列是否已经满。如果工作队列没有满,则将新提交的任务存储在这个工作队列里进行等待。如果工作队列满了,则执行第三步
3、线程池判断线程池的线程是否都处于工作状态。如果没有,则创建一个新的工作线程来执行任务。如果已经满了,则交给饱和策略来处理这个任务
线程池饱和策略
这里提到了线程池的饱和策略,那我们就简单介绍下有哪些饱和策略:
AbortPolicy
为Java线程池默认的阻塞策略,不执行此任务,而且直接抛出一个运行时异常,切记ThreadPoolExecutor.execute需要try catch,否则程序会直接退出。
DiscardPolicy
直接抛弃,任务不执行,空方法
DiscardOldestPolicy
从队列里面抛弃head的一个任务,并再次execute 此task。
CallerRunsPolicy
在调用execute的线程里面执行此command,会阻塞入口
用户自定义拒绝策略(最常用)
实现RejectedExecutionHandler,并自己定义策略模式
下我们以ThreadPoolExecutor为例展示下线程池的工作流程图
3.jpg
关键方法源码分析
我们看看核心方法添加到线程池方法execute的源码如下:
// //Executes the given task sometime in the future. The task //may execute in a new thread or in an existing pooled thread. // // If the task cannot be submitted for execution, either because this // executor has been shutdown or because its capacity has been reached, // the task is handled by the current {@code RejectedExecutionHandler}. // // @param command the task to execute // @throws RejectedExecutionException at discretion of // {@code RejectedExecutionHandler}, if the task // cannot be accepted for execution // @throws NullPointerException if {@code command} is null // public void execute(Runnable command) { if (command == null) throw new NullPointerException(); // // Proceed in 3 steps: // // 1. If fewer than corePoolSize threads are running, try to // start a new thread with the given command as its first // task. The call to addWorker atomically checks runState and // workerCount, and so prevents false alarms that would add // threads when it shouldn't, by returning false. // 翻译如下: // 判断当前的线程数是否小于corePoolSize如果是,使用入参任务通过addWord方法创建一个新的线程, // 如果能完成新线程创建exexute方法结束,成功提交任务 // 2. If a task can be successfully queued, then we still need // to double-check whether we should have added a thread // (because existing ones died since last checking) or that // the pool shut down since entry into this method. So we // recheck state and if necessary roll back the enqueuing if // stopped, or start a new thread if there are none. // 翻译如下: // 在第一步没有完成任务提交;状态为运行并且能否成功加入任务到工作队列后,再进行一次check,如果状态 // 在任务加入队列后变为了非运行(有可能是在执行到这里线程池shutdown了),非运行状态下当然是需要 // reject;然后再判断当前线程数是否为0(有可能这个时候线程数变为了0),如是,新增一个线程; // 3. If we cannot queue task, then we try to add a new // thread. If it fails, we know we are shut down or saturated // and so reject the task. // 翻译如下: // 如果不能加入任务到工作队列,将尝试使用任务新增一个线程,如果失败,则是线程池已经shutdown或者线程池 // 已经达到饱和状态,所以reject这个他任务 // int c = ctl.get(); // 工作线程数小于核心线程数 if (workerCountOf(c) < corePoolSize) { // 直接启动新线程,true表示会再次检查workerCount是否小于corePoolSize if (addWorker(command, true)) return; c = ctl.get(); } // 如果工作线程数大于等于核心线程数 // 线程的的状态未RUNNING并且队列notfull if (isRunning(c) && workQueue.offer(command)) { // 再次检查线程的运行状态,如果不是RUNNING直接从队列中移除 int recheck = ctl.get(); if (! isRunning(recheck) && remove(command)) // 移除成功,拒绝该非运行的任务 reject(command); else if (workerCountOf(recheck) == 0) // 防止了SHUTDOWN状态下没有活动线程了,但是队列里还有任务没执行这种特殊情况。 // 添加一个null任务是因为SHUTDOWN状态下,线程池不再接受新任务 addWorker(null, false); } // 如果队列满了或者是非运行的任务都拒绝执行 else if (!addWorker(command, false)) reject(command); }
E. 鑳借В閲娄竴涓媕ava镄勭嚎绋嬬殑浣跨敤
闅忕潃璁$畻链虹殑椋为熷彂灞曪纴涓浜鸿$畻链轰笂镄勬搷浣灭郴缁熶篃绾风悍閲囩敤澶氢换锷″拰鍒嗘椂璁捐★纴灏嗘棭链熷彧链夊ぇ鍨嬭$畻链烘墠鍏锋湁镄勭郴缁熺壒镐у甫鍒颁简涓浜鸿$畻链虹郴缁熶腑銆备竴鑸鍙浠ュ湪钖屼竴镞堕棿鍐呮墽琛屽氢釜绋嫔簭镄勬搷浣灭郴缁熼兘链夎繘绋嬬殑姒傚康銆备竴涓杩涚▼灏辨槸涓涓镓ц屼腑镄勭▼搴忥纴钥屾疮涓涓杩涚▼閮芥湁镊宸辩嫭绔嬬殑涓鍧楀唴瀛樼┖闂淬佷竴缁勭郴缁熻祫婧愩傚湪杩涚▼姒傚康涓锛屾疮涓涓杩涚▼镄勫唴閮ㄦ暟鎹鍜岀姸镐侀兘鏄瀹屽叏镫绔嬬殑銆侸ava绋嫔簭阃氲繃娴佹带鍒舵潵镓ц岀▼搴忔祦锛岀▼搴忎腑鍗曚釜椤哄簭镄勬祦鎺у埗绉颁负绾跨▼锛屽氱嚎绋嫔垯鎸囩殑鏄鍦ㄥ崟涓绋嫔簭涓鍙浠ュ悓镞惰繍琛屽氢釜涓嶅悓镄勭嚎绋嬶纴镓ц屼笉钖岀殑浠诲姟銆傚氱嚎绋嬫剰锻崇潃涓涓绋嫔簭镄勫氲岃鍙ュ彲浠ョ湅涓婂幓鍑犱箮鍦ㄥ悓涓镞堕棿鍐呭悓镞惰繍琛屻
绾跨▼涓庤繘绋嬬浉浼硷纴鏄涓娈靛畬鎴愭煇涓鐗瑰畾锷熻兘镄勪唬镰侊纴鏄绋嫔簭涓鍗曚釜椤哄簭镄勬祦鎺у埗锛涗絾涓庤繘绋嬩笉钖岀殑鏄锛屽悓绫荤殑澶氢釜绾跨▼鏄鍏变韩涓鍧楀唴瀛樼┖闂村拰涓缁勭郴缁熻祫婧愶纴钥岀嚎绋嬫湰韬镄勬暟鎹阃氩父鍙链夊井澶勭悊鍣ㄧ殑瀵勫瓨鍣ㄦ暟鎹锛屼互鍙娄竴涓渚涚▼搴忔墽琛屾椂浣跨敤镄勫爢镙堛傛墍浠ョ郴缁熷湪浜х敓涓涓绾跨▼锛屾垨钥呭湪钖勪釜绾跨▼涔嬮棿鍒囨崲镞讹纴璐熸媴瑕佹瘆杩涚▼灏忕殑澶氾纴姝e洜濡傛わ纴绾跨▼琚绉颁负杞昏礋钻疯繘绋嬶纸light-weight process锛夈备竴涓杩涚▼涓鍙浠ュ寘钖澶氢釜绾跨▼銆
涓涓绾跨▼鏄涓涓绋嫔簭鍐呴儴镄勯‘搴忔带鍒舵祦銆
1. 杩涚▼锛氭疮涓杩涚▼閮芥湁镫绔嬬殑浠g爜鍜屾暟鎹绌洪棿锛堣繘绋嬩笂涓嬫枃锛 锛岃繘绋嫔垏鎹㈢殑寮阌澶с
2. 绾跨▼锛氲交閲忕殑杩涚▼锛屽悓涓绫荤嚎绋嫔叡浜浠g爜鍜屾暟鎹绌洪棿锛屾疮涓绾跨▼链夌嫭绔嬬殑杩愯屾爤鍜岀▼搴忚℃暟鍣锛圥C锛夛纴绾跨▼鍒囨崲镄勫紑阌灏忋
3. 澶氲繘绋嬶细鍦ㄦ搷浣灭郴缁熶腑锛岃兘钖屾椂杩愯屽氢釜浠诲姟绋嫔簭銆
4. 澶氱嚎绋嬶细鍦ㄥ悓涓搴旂敤绋嫔簭涓锛屾湁澶氢釜椤哄簭娴佸悓镞舵墽琛屻
6锛1锛1 绾跨▼镄勬傚康妯″瀷
Java鍐呭湪鏀鎸佸氱嚎绋嬶纴瀹幂殑镓链夌被閮芥槸鍦ㄥ氱嚎绋嬩笅瀹氢箟镄勶纴Java鍒╃敤澶氱嚎绋嬩娇鏁翠釜绯荤粺鎴愪负寮傛ョ郴缁熴侸ava涓镄勭嚎绋嬬敱涓夐儴鍒嗙粍鎴愶纴濡傚浘6.1镓绀恒
1. 铏氭嫙镄凛PU锛屽皝瑁呭湪Java.lang.Thread绫讳腑銆
2. CPU镓镓ц岀殑浠g爜锛屼紶阃掔粰Thread绫汇
3. CPU镓澶勭悊镄勬暟鎹锛屼紶阃掔粰Thread绫汇
锲6.1绾跨▼
6. 1. 2 绾跨▼浣(1)
Java镄勭嚎绋嬫槸阃氲繃Java.lang.Thread绫绘潵瀹炵幇镄勚傚綋鎴戜滑鐢熸垚涓涓猅hread绫荤殑瀵硅薄涔嫔悗,涓涓鏂扮殑绾跨▼灏变骇鐢熶简銆
姝ょ嚎绋嫔疄渚嬭〃绀筼ava瑙i喷鍣ㄤ腑镄勭湡姝g殑绾跨▼锛岄氲繃瀹冨彲浠ュ惎锷ㄧ嚎绋嬨佺粓姝㈢嚎绋嬨佺嚎绋嬫寕璧风瓑锛屾疮涓绾跨▼閮芥槸阃氲繃绫籘hread鍦↗ava镄勮蒋浠跺寘Java.lang涓瀹氢箟锛屽畠镄勬瀯阃犳柟娉曚负锛
public Thread 锛圱hreadGroup group锛孯unnable target锛孲tring name锛夛绂
鍏朵腑锛実roup 鎸囨槑璇ョ嚎绋嬫墍灞炵殑绾跨▼缁勶绂target瀹为檯镓ц岀嚎绋嬩綋镄勭洰镙囧硅薄锛屽畠蹇呴’瀹炵幇鎺ュ彛Runnable锛 name涓虹嚎绋嫔悕銆侸ava涓镄勬疮涓绾跨▼閮芥湁镊宸辩殑钖岖О锛孞ava鎻愪緵浜嗕笉钖孴hread绫绘瀯阃犲櫒锛屽厑璁哥粰绾跨▼鎸囧畾钖岖О銆傚傛灉name涓簄ull镞讹纴鍒橨ava镊锷ㄦ彁渚涘敮涓镄勫悕绉般
褰扑笂杩版瀯阃犳柟娉旷殑镆愪釜鍙傛暟涓簄ull镞讹纴鎴戜滑鍙寰楀埌涓嬮溃镄勫嚑涓鏋勯犳柟娉曪细
public Thread 锛堬级锛
public Thread 锛圧unnable target锛夛绂
public Thread 锛圧unnable target锛孲tring name锛夛绂
public Thread 锛圫tring name锛夛绂
public Thread 锛圱hreadGroup group锛孯unnable target锛夛绂
public Thread 锛圱hreadGroup group锛孲tring name锛夛绂
涓涓绫诲0鏄庡疄鐜癛unnable鎺ュ彛灏卞彲浠ュ厖褰撶嚎绋嬩綋锛屽湪鎺ュ彛Runnable涓鍙瀹氢箟浜嗕竴涓鏂规硶 run锛堬级锛
public void run锛堬级锛
浠讳綍瀹炵幇鎺ュ彛Runnable镄勫硅薄閮藉彲浠ヤ綔涓轰竴涓绾跨▼镄勭洰镙囧硅薄锛岀被Thread链韬涔熷疄鐜颁简鎺ュ彛Runnable锛屽洜姝ゆ垜浠鍙浠ラ氲繃涓ょ嶆柟娉曞疄鐜扮嚎绋嬩綋銆
锛堜竴锛夊畾涔変竴涓绾跨▼绫伙纴瀹幂户镓跨嚎绋嬬被Thread骞堕吨鍐椤叾涓镄勬柟娉 run锛堬级锛岃繖镞跺湪鍒濆嫔寲杩欎釜绫荤殑瀹炰緥镞讹纴鐩镙噒arget鍙涓簄ull锛岃〃绀虹敱杩欎釜瀹炰緥瀵规潵镓ц岀嚎绋嬩綋銆傜敱浜嶫ava鍙鏀鎸佸崟閲岖户镓匡纴鐢ㄨ繖绉嶆柟娉曞畾涔夌殑绫讳笉鑳藉啀缁ф圹鍏跺畠鐖剁被銆
锛堜簩锛夋彁渚涗竴涓瀹炵幇鎺ュ彛Runnable镄勭被浣滀负涓涓绾跨▼镄勭洰镙囧硅薄锛屽湪鍒濆嫔寲涓涓猅hread绫绘垨钥匮hread瀛愮被镄勭嚎绋嫔硅薄镞讹纴鎶婄洰镙囧硅薄浼犻掔粰杩欎釜绾跨▼瀹炰緥锛岀敱璇ョ洰镙囧硅薄鎻愪緵绾跨▼浣 run锛堬级銆傝繖镞讹纴瀹炵幇鎺ュ彛Runnable镄勭被浠岖劧鍙浠ョ户镓垮叾瀹幂埗绫汇
姣忎釜绾跨▼閮芥槸阃氲繃镆愪釜鐗瑰畾Thread瀵硅薄镄勬柟娉时un( )𨱒ュ畬鎴愬叾镎崭綔镄勶纴鏂规硶run( )绉颁负绾跨▼浣撱傚浘6.2琛ㄧず浜呙ava绾跨▼镄勪笉钖岀姸镐佷互鍙婄姸镐佷箣闂磋浆鎹㈡墍璋幂敤镄勬柟娉曘
锲6.2 绾跨▼镄勭姸镐
1. 鍒涘缓鐘舵(new Thread)
镓ц屼笅鍒楄鍙ユ椂锛岀嚎绋嫔氨澶勪簬鍒涘缓鐘舵侊细
Thread myThread = new MyThreadClass( );
褰扑竴涓绾跨▼澶勪簬鍒涘缓鐘舵佹椂锛屽畠浠呬粎鏄涓涓绌虹殑绾跨▼瀵硅薄锛岀郴缁熶笉涓哄畠鍒嗛厤璧勬簮銆
2. 鍙杩愯岀姸镐( Runnable )
Thread myThread = new MyThreadClass( );
myThread.start( );
褰扑竴涓绾跨▼澶勪簬鍙杩愯岀姸镐佹椂锛岀郴缁熶负杩欎釜绾跨▼鍒嗛厤浜嗗畠闇镄勭郴缁熻祫婧愶纴瀹夋帓鍏惰繍琛屽苟璋幂敤绾跨▼杩愯屾柟娉曪纴杩欐牱灏变娇寰楄ョ嚎绋嫔勪簬鍙杩愯( Runnable )鐘舵併傞渶瑕佹敞镒忕殑鏄杩欎竴鐘舵佸苟涓嶆槸杩愯屼腑鐘舵侊纸Running )锛屽洜涓虹嚎绋嬩篃璁稿疄闄呬笂骞舵湭鐪熸h繍琛屻傜敱浜庡緢澶氲$畻链洪兘鏄鍗曞勭悊鍣ㄧ殑锛屾墍浠ヨ佸湪钖屼竴镞跺埢杩愯屾墍链夌殑澶勪簬鍙杩愯岀姸镐佺殑绾跨▼鏄涓嶅彲鑳界殑锛孞ava镄勮繍琛岀郴缁熷繀椤诲疄鐜拌皟搴︽潵淇濊瘉杩欎簺绾跨▼鍏变韩澶勭悊鍣ㄣ
3. 涓嶅彲杩愯岀姸镐侊纸Not Runnable锛
杩涘叆涓嶅彲杩愯岀姸镐佺殑铡熷洜链夊备笅鍑犳浔锛
1) 璋幂敤浜唖leep锛堬级鏂规硶;
2) 璋幂敤浜唖uspend锛堬级鏂规硶;
3) 涓虹瓑鍊欎竴涓𨱒′欢鍙橀噺锛岀嚎绋嬭皟鐢╳ait锛堬级鏂规硶;
4) 杈揿叆杈揿嚭娴佷腑鍙戠敓绾跨▼阒诲;
涓嶅彲杩愯岀姸镐佷篃绉颁负阒诲炵姸镐侊纸Blocked锛夈傚洜涓烘煇绉嶅师锲狅纸杈揿叆/杈揿嚭銆佺瓑寰呮秷鎭鎴栧叾瀹冮樆濉炴儏鍐碉级锛岀郴缁熶笉鑳芥墽琛岀嚎绋嬬殑鐘舵併傝繖镞跺嵆浣垮勭悊鍣ㄧ┖闂诧纴涔熶笉鑳芥墽琛岃ョ嚎绋嬨
4. 姝讳骸鐘舵侊纸Dead锛
绾跨▼镄勭粓姝涓鑸鍙阃氲繃涓ょ嶆柟娉曞疄鐜帮细镊铹舵挙娑堬纸绾跨▼镓ц屽畬锛夋垨鏄琚锅沧锛堣皟鐢╯top()鏂规硶锛夈傜洰鍓崭笉鎺ㄨ崘阃氲繃璋幂敤stop()𨱒ョ粓姝㈢嚎绋嬬殑镓ц岋纴钥屾槸璁╃嚎绋嬫墽琛屽畬銆
http://www.bc-cn.net/Article/kfyy/java/jc/200410/83.html