คำนำ
บทความก่อนหน้านี้มุ่งเน้นไปที่การเพิ่มประสิทธิภาพของฐานข้อมูลบริการแบ็คเอนด์และการประมวลผลแบบขนานแบบมัลติเธรดและตัวอย่างของตรรกะ pseudocode ก่อนและหลังการแปลง แน่นอนว่าการเพิ่มประสิทธิภาพนั้นไม่มีที่สิ้นสุด รุ่นก่อนหน้าปลูกต้นไม้และคนรุ่นต่อ ๆ มาเพลิดเพลินไปกับร่มเงา ในขณะที่นักพัฒนาของเราเนื่องจากเรายืนอยู่บนไหล่ของไจแอนต์เราต้องเขียนโปรแกรมที่ได้รับการปรับปรุงให้ดีขึ้น
กรณีการพัฒนา Springboot JDBCTEMPLATE BATCH
กรณีการพัฒนา Springboot: การประมวลผลแบบมัลติทาสกิ้งมัลติทาสกิ้ง
การปรับปรุงใหม่
ในทางทฤษฎียิ่งมีเธรดมากเท่าไหร่โปรแกรมก็เร็วขึ้น แต่ในการใช้งานจริงเราจำเป็นต้องพิจารณาการใช้ทรัพยากรของเธรดเองสร้างและทำลายล้างรวมถึงวัตถุประสงค์ในการปกป้องระบบปฏิบัติการเอง เรามักจะต้อง จำกัด เธรดให้อยู่ในช่วงที่แน่นอนและพูลเธรดมีบทบาทนี้
ตรรกะของโปรแกรม
มัลติทาสก์คู่ขนาน + การประมวลผลพูลเธรด png
ปัญหาที่สามารถแก้ไขได้จากรูปภาพควรมีน้อยที่สุดเท่าที่จะทำได้ แน่นอนหลักการพื้นฐานยังคงต้องจดจำและเข้าใจโดยทุกคน
พูลเธรด Java
Java จัดหาพูลเธรดสี่ประเภทผ่านผู้บริหารคือ:
ข้อได้เปรียบ
การใช้รหัส
วิธีที่ 1 (Countdownlatch)
/*** มัลติทาสกิ้งแบบขนาน + สถิติพูลเธรด* เวลาการสร้าง 17 เมษายน 2018*/ชั้นเรียนสาธารณะ statsdemo {สุดท้ายคงที่ simpledateFormat SDF = ใหม่ SimpledateFormat ("YYYY-MM-DD HH: MM: SS"); สตริงคงสุดท้าย starttime = sdf.format (วันที่ใหม่ ()); / ** * งานที่เข้มข้นของ IO = โดยทั่วไป 2 * จำนวนคอร์ CPU (มักจะอยู่ในเธรด: การโต้ตอบข้อมูลฐานข้อมูล, การอัปโหลดและดาวน์โหลดไฟล์, การส่งข้อมูลเครือข่าย ฯลฯ ) * งานที่เข้มข้นของ CPU = CPU CORES 1 CPU runtime.getRuntime (). arableprocessors (); /*** Public Threadpoolexecutor (int corepoolsize, int maximumpoolsize, quetalivetime ยาว,* unit timeunit, การปิดกั้น) <runnable> workqueue)* corepoolsize ใช้เพื่อระบุจำนวนของด้ายหลัก คิวบัฟเฟอร์ของพูลเธรดและเธรดที่ยังไม่ได้ดำเนินการจะรออยู่ในคิว* ความยาวคิวการตรวจสอบคิวเพื่อให้แน่ใจว่าคิวที่มีขอบเขต* ขนาดพูลเธรดที่ไม่เหมาะสมสามารถชะลอความเร็วในการประมวลผลลดความเสถียรและนำไปสู่การรั่วไหลของหน่วยความจำ หากมีการกำหนดค่าเธรดน้อยเกินไปคิวจะยังคงเติบโตมากขึ้นและใช้หน่วยความจำมากเกินไป * และเธรดมากเกินไปจะชะลอความเร็วของระบบทั้งหมดเนื่องจากการสลับบริบทบ่อยครั้ง - และผลลัพธ์สุดท้ายจะเกิดขึ้นได้ ความยาวของคิวมีความสำคัญจะต้องมีขอบเขตเพื่อให้หากพูลเธรดถูกครอบงำมันสามารถปฏิเสธคำขอใหม่ได้ชั่วคราว * การใช้งานเริ่มต้นของ ExecutorService เป็น LinkedBlockingQueue ที่ไม่มีขอบเขต */ Private Static ThreadPoolexecutor Executor = ใหม่ ThreadPoolexecutor (CorePoolSize, CorePoolSize+1, 10L, TimeUnit.Seconds, LinkedBlockingQueue ใหม่ <Runnable> (1,000)); โมฆะคงที่สาธารณะหลัก (String [] args) พ่น InterruptedException {Countdownlatch latch = new Countdownlatch (5); // ใช้วิธีดำเนินการ Executor.Execute (สถิติใหม่ ("Task A", 1000, latch)); Executor.Execute (สถิติใหม่ ("Task B", 1,000, latch)); Executor.Execute (สถิติใหม่ ("Task C", 1,000, latch)); Executor.Execute (สถิติใหม่ ("Task D", 1,000, latch)); Executor.Execute (สถิติใหม่ ("Task E", 1,000, latch)); latch.await (); // รองานของทุกคนเพื่อสิ้นสุด System.out.println ("การดำเนินงานทางสถิติทั้งหมดเสร็จสิ้น:" + sdf.format (วันที่ใหม่ ())); } สถิติคลาสสแตติกใช้การเรียกใช้ {String StatSname; Int Runtime; Latch Countdownlatch; สถิติสาธารณะ (String StatSname, Int Runtime, CountdownLatch latch) {this.statsName = statSname; this.runtime = runtime; this.latch = latch; } โมฆะสาธารณะเรียกใช้ () {ลอง {system.out.println (statsname+ "สถิติเริ่มต้นที่"+ starttime); // จำลองภารกิจการดำเนินการตามเวลา thread.sleep (รันไทม์); System.out.println (StatSname + "Do Stats เสร็จสมบูรณ์ที่" + sdf.format (วันที่ใหม่ ())); latch.countdown (); // งานเดียวสิ้นสุดลงเคาน์เตอร์จะลดลงหนึ่ง} catch (interruptedException e) {e.printstacktrace (); -วิธีที่ 2 (อนาคต)
/*** มัลติทาสกิ้งแบบขนาน + สถิติพูลเธรด* เวลาการสร้าง 17 เมษายน 2018*/ชั้นเรียนสาธารณะ statsdemo {สุดท้ายคงที่ simpledateFormat SDF = ใหม่ SimpledateFormat ("YYYY-MM-DD HH: MM: SS"); สตริงคงสุดท้าย starttime = sdf.format (วันที่ใหม่ ()); / ** * งานที่เข้มข้นของ IO = โดยทั่วไป 2 * จำนวนคอร์ CPU (มักจะอยู่ในเธรด: การโต้ตอบข้อมูลฐานข้อมูล, การอัปโหลดและดาวน์โหลดไฟล์, การส่งข้อมูลเครือข่าย ฯลฯ ) * งานที่เข้มข้นของ CPU = CPU CORES 1 CPU runtime.getRuntime (). arableprocessors (); /*** Public Threadpoolexecutor (int corepoolsize, int maximumpoolsize, quetalivetime ยาว,* unit timeunit, การปิดกั้น) <runnable> workqueue)* corepoolsize ใช้เพื่อระบุจำนวนของด้ายหลัก คิวบัฟเฟอร์ของพูลเธรดและเธรดที่ยังไม่ได้ดำเนินการจะรออยู่ในคิว* ความยาวคิวการตรวจสอบคิวเพื่อให้แน่ใจว่าคิวที่มีขอบเขต* ขนาดพูลเธรดที่ไม่เหมาะสมสามารถชะลอความเร็วในการประมวลผลลดความเสถียรและนำไปสู่การรั่วไหลของหน่วยความจำ หากมีการกำหนดค่าเธรดน้อยเกินไปคิวจะยังคงเติบโตมากขึ้นและใช้หน่วยความจำมากเกินไป * และเธรดมากเกินไปจะชะลอความเร็วของระบบทั้งหมดเนื่องจากการสลับบริบทบ่อยครั้ง - และผลลัพธ์สุดท้ายจะเกิดขึ้นได้ ความยาวของคิวมีความสำคัญจะต้องมีขอบเขตเพื่อให้หากพูลเธรดถูกครอบงำมันสามารถปฏิเสธคำขอใหม่ได้ชั่วคราว * การใช้งานเริ่มต้นของ ExecutorService เป็น LinkedBlockingQueue ที่ไม่มีขอบเขต */ Private Static ThreadPoolexecutor Executor = ใหม่ ThreadPoolexecutor (CorePoolSize, CorePoolSize+1, 10L, TimeUnit.Seconds, LinkedBlockingQueue ใหม่ <Runnable> (1,000)); โมฆะคงที่สาธารณะหลัก (String [] args) พ่น InterruptedException {list <Future <String>> resultList = new ArrayList <Future <String>> (); // ใช้งานแบบอะซิงโครนัสและรับค่าส่งคืนเป็น future resultlist.add (executor.submit (สถิติใหม่ ("งาน A", 1,000))); resultlist.add (executor.submit (สถิติใหม่ ("งาน B", 1000))); resultlist.add (executor.submit (สถิติใหม่ ("งาน C", 1000))); resultlist.add (executor.submit (สถิติใหม่ ("งาน D", 1000))); resultlist.add (executor.submit (สถิติใหม่ ("งาน e", 1000))); // ผลลัพธ์ของงาน traversal สำหรับ (อนาคต <String> fs: resultlist) {ลอง {system.out.println (fs.get ()); // พิมพ์ผลลัพธ์ของการดำเนินการงานแต่ละบรรทัดโทร Future.get () เพื่อบล็อกเธรดหลัก } catch (ExecutionException E) {E.printStackTrace (); } ในที่สุด {// เริ่มหนึ่งครั้งและดำเนินการงานที่ส่งมาก่อนหน้านี้ แต่ไม่ยอมรับงานใหม่ หากปิดการโทรจะไม่มีผลกระทบอื่น Executor.shutdown (); }} system.out.println ("งานทางสถิติทั้งหมดดำเนินการ:" + sdf.format (วันที่ใหม่ ())); } สถิติคลาสคงที่ใช้ callable <string> {String StatSname; Int Runtime; สถิติสาธารณะ (String StatSname, int runtime) {this.statsName = statSname; this.runtime = runtime; } การเรียกสตริงสาธารณะ () {ลอง {system.out.println (statsname+ "สถิติเริ่มต้นที่"+ starttime); // จำลองภารกิจการดำเนินการตามเวลา thread.sleep (รันไทม์); System.out.println (StatSname + "Do Stats เสร็จสมบูรณ์ที่" + sdf.format (วันที่ใหม่ ())); } catch (interruptedException e) {e.printStackTrace (); } return call (); -เวลาดำเนินการ
รหัสข้างต้นคือรหัสหลอกทั้งหมดและต่อไปนี้เป็นบันทึกการทดสอบจริงของนักเรียนมากกว่า 2,000 คน
2018-04-17 17: 42: 29.284 ข้อมูลการทดสอบข้อมูลบันทึก 81E51AB031EB4ADA92743DDF66528D82-Single-Threaded Sequential การดำเนินการตามลำดับเวลา: 3797
2018-04-17 17: 42: 31.452 ข้อมูลการทดสอบข้อมูลบันทึก 81E51AB031EB4ADA92743DDF66528D82 ภารกิจคู่ขนานที่ใช้เวลา: 2167
2018-04-17 17: 42: 33.170 ข้อมูลการทดสอบข้อมูลบันทึก 81E51AB031EB4ADA92743DDF66528D82 ภารกิจขนานแบบขนาน + พูลเธรดเวลา: 1717
ข้างต้นเป็นเนื้อหาทั้งหมดของบทความนี้ ฉันหวังว่ามันจะเป็นประโยชน์ต่อการเรียนรู้ของทุกคนและฉันหวังว่าทุกคนจะสนับสนุน wulin.com มากขึ้น