ตัวอย่างในบทความนี้สรุปเทคนิคการปรับประสิทธิภาพการทำงานของ Java ให้เหมาะสม แบ่งปันกับทุกคนสำหรับการอ้างอิงของคุณ การวิเคราะห์เฉพาะมีดังนี้:
ที่นี่เราอ้างถึงหนังสือและทรัพยากรเครือข่ายบางเล่มซึ่งเหมาะสำหรับแอปพลิเคชัน Java ส่วนใหญ่
ในโปรแกรม JAVA สาเหตุของปัญหาประสิทธิภาพส่วนใหญ่ไม่ได้อยู่ที่ภาษา JAVA แต่อยู่ที่ตัวโปรแกรมเอง การพัฒนานิสัยการเขียนโค้ดที่ดีเป็นสิ่งสำคัญมากและสามารถปรับปรุงประสิทธิภาพของโปรแกรมได้อย่างมาก
1. ลองใช้ตัวแก้ไขขั้นสุดท้าย
คลาสที่มีตัวแก้ไขขั้นสุดท้ายจะไม่ได้รับมา ใน JAVA core API มีตัวอย่างการใช้ขั้นสุดท้ายมากมาย เช่น java.lang.String การระบุขั้นสุดท้ายสำหรับคลาส String จะป้องกันไม่ให้ผู้ใช้แทนที่เมธอด length() นอกจากนี้ หากคลาสเป็นที่สิ้นสุด วิธีการทั้งหมดของคลาสถือเป็นที่สิ้นสุด คอมไพเลอร์ Java จะมองหาโอกาสในการอินไลน์วิธีการสุดท้ายทั้งหมด (ขึ้นอยู่กับการใช้งานคอมไพเลอร์เฉพาะ) สิ่งนี้สามารถปรับปรุงประสิทธิภาพได้โดยเฉลี่ย 50%
2. พยายามนำสิ่งของต่างๆ มาใช้ซ้ำ
โดยเฉพาะอย่างยิ่งเมื่อใช้ String object ควรใช้ StringBuffer แทนเมื่อ string concatenation เกิดขึ้น เนื่องจากระบบไม่เพียงแต่ต้องใช้เวลาในการสร้าง object เท่านั้น แต่ยังอาจต้องใช้เวลาในการรวบรวมและประมวลผล object เหล่านี้ในอนาคตอีกด้วย ดังนั้นการสร้างอ็อบเจ็กต์มากเกินไปจะมีผลกระทบอย่างมากต่อประสิทธิภาพของโปรแกรม
3. ลองใช้ตัวแปรท้องถิ่น
พารามิเตอร์ที่ส่งผ่านเมื่อเรียกใช้เมธอดและตัวแปรชั่วคราวที่สร้างขึ้นระหว่างการโทรจะถูกบันทึกไว้ในสแต็ก (สแต็ก) ซึ่งเร็วกว่า ตัวแปรอื่นๆ เช่น ตัวแปรคงที่ ตัวแปรอินสแตนซ์ ฯลฯ จะถูกสร้างขึ้นในฮีปและทำงานช้ากว่า
4. อย่าเริ่มต้นตัวแปรซ้ำๆ
ตามค่าเริ่มต้น เมื่อเรียก Constructor ของคลาส Java จะเตรียมใช้งานตัวแปรให้เป็นค่าที่กำหนด ออบเจ็กต์ทั้งหมดจะถูกตั้งค่าเป็น null ตัวแปรจำนวนเต็มจะถูกตั้งค่าเป็น 0 ตัวแปร float และ double จะถูกตั้งค่าเป็น 0.0 และค่าตรรกะจะถูกตั้งค่าเป็น เท็จ. สิ่งนี้ควรสังเกตเป็นพิเศษเมื่อคลาสได้รับมาจากคลาสอื่น เนื่องจากเมื่อวัตถุถูกสร้างขึ้นโดยใช้คีย์เวิร์ดใหม่ ตัวสร้างทั้งหมดในสายตัวสร้างจะถูกเรียกโดยอัตโนมัติ
มีหมายเหตุอยู่ที่นี่ เมื่อตั้งค่าเริ่มต้นสำหรับตัวแปรสมาชิกแต่จำเป็นต้องเรียกใช้วิธีอื่น ทางที่ดีควรใส่ไว้ในวิธีเช่น initXXX() เนื่องจากการเรียกวิธีการกำหนดค่าโดยตรงอาจทำให้เกิดค่าว่าง ข้อยกเว้นของตัวชี้เนื่องจากยังไม่ได้เตรียมใช้งานคลาส public int state = this.getState();
5. ในการพัฒนาระบบแอปพลิเคชัน Java+Oracle ภาษา SQL ที่ฝังอยู่ใน Java ควรเป็นตัวพิมพ์ใหญ่ให้มากที่สุดเพื่อลดภาระการแยกวิเคราะห์ของ Oracle parser
6. ในระหว่างขั้นตอนการเขียนโปรแกรม Java ให้ดำเนินการเชื่อมต่อฐานข้อมูลและการดำเนินการสตรีม I/O หลังจากใช้งาน ให้ปิดให้ทันเวลาเพื่อเผยแพร่ทรัพยากร เนื่องจากการดำเนินการกับวัตถุขนาดใหญ่เหล่านี้จะทำให้ระบบมีค่าใช้จ่ายจำนวนมาก
7. การสร้างออบเจ็กต์มากเกินไปจะใช้หน่วยความจำระบบจำนวนมาก และในกรณีร้ายแรง อาจทำให้หน่วยความจำรั่วได้ ดังนั้นจึง มีความสำคัญอย่างยิ่งที่จะต้องรีไซเคิลออบเจ็กต์ที่หมดอายุอย่างทันท่วงที
GC ของ JVM ไม่ฉลาดนัก ดังนั้นจึงแนะนำให้ตั้งค่าเป็น null ด้วยตนเองหลังจากใช้อ็อบเจ็กต์
8. เมื่อใช้กลไกการซิงโครไนซ์ ให้ลองใช้วิธีซิงโครไนซ์แทนการซิงโครไนซ์บล็อคโค้ด
9. ลดการนับตัวแปรซ้ำให้เหลือน้อยที่สุด
ตัวอย่างเช่น
สำหรับ(int i=0;i<list.size();i++)
ควรปรับเปลี่ยนเป็น
สำหรับ(int i=0,len=list.size();i<len;i++)
10. ใช้กลยุทธ์ในการสร้างเมื่อคุณต้องการเท่านั้น
ตัวอย่างเช่น:
สตริง str="abc";if(i==1){ list.add(str);}
ควรแก้ไขเป็น:
if(i==1){String str="abc"; list.add(str);}
11. ใช้ข้อยกเว้นด้วยความระมัดระวัง เนื่องจากข้อยกเว้นเป็นอันตรายต่อประสิทธิภาพการทำงาน
การโยนข้อยกเว้นก่อนจะสร้างวัตถุใหม่ ตัวสร้างของอินเทอร์เฟซ Throwable เรียกเมธอดท้องถิ่นชื่อ fillInStackTrace() เมธอด fillInStackTrace() จะตรวจสอบสแต็กและรวบรวมข้อมูลการติดตามการโทร เมื่อใดก็ตามที่มีข้อยกเว้นเกิดขึ้น VM จะต้องปรับ call stack เนื่องจากมีการสร้างออบเจ็กต์ใหม่ในระหว่างการประมวลผล
ข้อยกเว้นควรใช้สำหรับการจัดการข้อผิดพลาดเท่านั้น และไม่ควรใช้เพื่อควบคุมโฟลว์ของโปรแกรม
12. อย่าใช้คำสั่ง Try/Catch ในลูป ควรวางไว้ที่ระดับนอกสุดของลูป
Error คือคลาสสำหรับรับข้อผิดพลาดของระบบหรือข้อผิดพลาดของเครื่องเสมือน ไม่สามารถรับข้อยกเว้นข้อผิดพลาดทั้งหมดได้ หากเครื่องเสมือนรายงานข้อผิดพลาด Exception คุณต้องใช้ข้อผิดพลาดเพื่อรับ
13. การตั้งค่าความจุเริ่มต้นของ StringBuffer ผ่านตัวสร้างสามารถปรับปรุงประสิทธิภาพได้อย่างมาก
ความจุเริ่มต้นของ StringBuffer คือ 16 เมื่อความจุของ StringBuffer ถึงความจุสูงสุด ความจุจะเพิ่มขึ้นเป็น 2 เท่า + 2 ของความจุปัจจุบัน ซึ่งก็คือ 2*n+2 เมื่อใดก็ตามที่ StringBuffer ถึงความจุสูงสุดของเธอ เธอจะต้องสร้างอาร์เรย์ของอ็อบเจ็กต์ใหม่ จากนั้นคัดลอกอาร์เรย์ของอ็อบเจ็กต์เก่า ซึ่งเสียเวลามาก ดังนั้นจึงจำเป็นต้องตั้งค่าความจุเริ่มต้นที่เหมาะสมสำหรับ StringBuffer!
14. ใช้ java.util.Vector อย่างสมเหตุสมผล
Vector คล้ายกับ StringBuffer ทุกครั้งที่ขยายความจุ องค์ประกอบที่มีอยู่ทั้งหมดจะต้องถูกกำหนดให้กับพื้นที่เก็บข้อมูลใหม่ ความจุเริ่มต้นของ Vector คือ 10 องค์ประกอบ และความจุเป็นสองเท่า
vector.add(index,obj) วิธีนี้สามารถแทรกองค์ประกอบ obj ไปที่ตำแหน่งดัชนี แต่ดัชนีและองค์ประกอบที่ตามมาจะต้องเลื่อนลงหนึ่งตำแหน่ง (เพิ่มดัชนีโดย 1) ไม่ดีต่อประสิทธิภาพเว้นแต่จำเป็น
กฎเดียวกันนี้ใช้กับเมธอด Remove(int Index) ซึ่งจะลบองค์ประกอบที่ตำแหน่งที่ระบุในเวกเตอร์นี้ เลื่อนองค์ประกอบที่ตามมาทั้งหมดไปทางซ้าย (ลดดัชนีลง 1) ส่งคืนองค์ประกอบที่ถูกลบออกจากเวกเตอร์นี้ ดังนั้นการลบองค์ประกอบสุดท้ายของเวกเตอร์จึงมีราคาถูกกว่าการลบองค์ประกอบแรกมาก วิธีที่ดีที่สุดคือใช้เมธอด RemoveAllElements() เพื่อลบองค์ประกอบทั้งหมด
หากคุณต้องการลบองค์ประกอบในเวกเตอร์ คุณสามารถใช้ vector.remove(obj) คุณไม่จำเป็นต้องดึงตำแหน่งองค์ประกอบด้วยตัวเองแล้วลบออก เช่น int index = indexOf(obj); ดัชนี);
15. เมื่อทำการคัดลอกข้อมูลจำนวนมาก ให้ใช้ System.arraycopy();
16. การปรับโครงสร้างโค้ดใหม่เพื่อเพิ่มความสามารถในการอ่านโค้ด
17. สร้างอินสแตนซ์ของออบเจ็กต์โดยไม่ต้องใช้คีย์เวิร์ดใหม่
เมื่อคุณสร้างอินสแตนซ์ของคลาสโดยใช้คีย์เวิร์ดใหม่ ตัวสร้างทั้งหมดในห่วงโซ่ตัวสร้างจะถูกเรียกโดยอัตโนมัติ แต่ถ้าวัตถุใช้อินเทอร์เฟซ Cloneable เราก็สามารถเรียกเมธอด clone() ของเธอได้ เมธอด clone() ไม่ได้เรียกตัวสร้างคลาสใดๆ
ต่อไปนี้คือการใช้งานทั่วไปของรูปแบบ Factory
เครดิตคงที่สาธารณะ getNewCredit(){ คืนเครดิตใหม่ ();} รหัสที่ปรับปรุงใช้วิธีโคลน () เครดิต BaseCredit ส่วนตัวคงที่ = เครดิตใหม่ (); เครดิตคงที่สาธารณะ getNewCredit () { กลับ (Credit) BaseCredit.clone () ;}
18. หากการแทนที่สามารถใช้สำหรับการคูณและการหารได้ การแทนที่ควรใช้ให้มากที่สุดเท่าที่จะเป็นไปได้ แต่ทางที่ดีควรเพิ่มความคิดเห็น เนื่องจากการดำเนินการแทนที่นั้นไม่เป็นไปตามสัญชาตญาณและเข้าใจยาก
19. อย่าประกาศอาร์เรย์เป็น: public static Final
20.การสำรวจเส้นทาง HaspMap
แผนที่<String, String[]> paraMap = new HashMap<String, String[]>();for( Entry<String, String[]> entry : paraMap.entrySet() ){ String appFieldDefId = entry.getKey(); ค่าสตริง [] = entry.getValue();}
ใช้ค่าแฮชเพื่อดึงข้อมูลรายการที่เกี่ยวข้องสำหรับการเปรียบเทียบเพื่อให้ได้ผลลัพธ์ หลังจากได้รับค่ารายการแล้ว ให้รับคีย์และค่าโดยตรง
21. การใช้อาร์เรย์ (array) และ ArrayList
อาเรย์อาร์เรย์มีประสิทธิภาพสูงสุด แต่ความจุคงที่และไม่สามารถเปลี่ยนแปลงแบบไดนามิกได้ ความจุของ ArrayList สามารถเพิ่มขึ้นแบบไดนามิกได้ แต่ประสิทธิภาพจะลดลง
22. เธรดเดี่ยวควรลองใช้ HashMap และ ArrayList หากไม่จำเป็น ไม่แนะนำให้ใช้ HashTable และ Vector พวกเขาใช้กลไกการซิงโครไนซ์และลดประสิทธิภาพ
23. ความแตกต่างระหว่าง StringBuffer และ StringBuilder คือ: java.lang.StringBuffer เป็นลำดับอักขระของตัวแปรที่ปลอดภัยสำหรับเธรด บัฟเฟอร์สตริงคล้ายกับ String แต่ไม่สามารถแก้ไขได้ StringBuilder โดยทั่วไปควรใช้คลาส StringBuilder ในการตั้งค่าให้กับคลาสนี้ เนื่องจากคลาสนี้สนับสนุนการดำเนินการเดียวกันทั้งหมด แต่จะเร็วกว่าเนื่องจากไม่ได้ทำการซิงโครไนซ์ เพื่อให้ได้ประสิทธิภาพที่ดีขึ้น คุณควรพยายามระบุความสามารถของเธอเมื่อสร้าง StringBuffer หรือ StringBuilder แน่นอนว่าไม่จำเป็นหากมีความยาวไม่เกิน 16 ตัวอักษร
ภายใต้สถานการณ์เดียวกัน การใช้ StringBuilder สามารถปรับปรุงประสิทธิภาพได้เพียง 10% ถึง 15% เมื่อเทียบกับการใช้ StringBuffer แต่จะเสี่ยงต่อความไม่มั่นคงของมัลติเธรด หลังจากพิจารณาอย่างครอบคลุมแล้ว ขอแนะนำให้ใช้ StringBuffer
24. พยายามใช้ชนิดข้อมูลพื้นฐานแทนวัตถุ
25. ใช้การคำนวณเชิงตัวเลขอย่างง่ายแทนการคำนวณฟังก์ชันที่ซับซ้อน เช่น ค้นหาตารางเพื่อแก้ปัญหาฟังก์ชันตรีโกณมิติ
26. การใช้การเปรียบเทียบที่เป็นรูปธรรมมีประสิทธิภาพมากกว่าการใช้อินเทอร์เฟซ แต่ความยืดหยุ่นของโครงสร้างลดลง แต่ IDE สมัยใหม่สามารถแก้ปัญหานี้ได้
27. พิจารณาใช้วิธีการคงที่
หากคุณไม่จำเป็นต้องเข้าถึงภายนอกวัตถุ ให้ทำให้วิธีการของคุณเป็นแบบคงที่ จะถูกเรียกเร็วขึ้นเพราะไม่ต้องใช้ตารางแนะนำฟังก์ชันเสมือน เพื่อนร่วมงานคนนี้ก็เป็นวิธีปฏิบัติที่ดีเช่นกัน เพราะเธอบอกวิธีแยกแยะลักษณะของวิธีการ การเรียกวิธีนี้จะไม่เปลี่ยนสถานะของวัตถุ
28. ควรหลีกเลี่ยงการใช้วิธี GET และ SET ภายในให้มากที่สุด
ในการเขียนโปรแกรม Android การเรียกใช้เมธอดเสมือนจะต้องเสียค่าใช้จ่ายจำนวนมาก ซึ่งแพงกว่าการสืบค้นแอตทริบิวต์อินสแตนซ์ เราควรใช้เมธอด get และ set เมื่อทำการเอาท์ซอร์สการโทรเท่านั้น แต่เมื่อโทรภายใน เราควรโทรหาพวกเขาโดยตรง
29. หลีกเลี่ยงการใช้การแจงนับและเลขทศนิยม
30. อาเรย์สองมิติใช้พื้นที่หน่วยความจำมากกว่าอาเรย์หนึ่งมิติ ประมาณ 10 เท่าของการคำนวณ
31. ฐานข้อมูล SQLite อ่านข้อมูลทั้งหมดของตารางทั้งหมดอย่างรวดเร็ว แต่การสืบค้นแบบมีเงื่อนไขจะใช้เวลา 30-50MS เมื่อทำเช่นนี้ ทุกคนควรใส่ใจกับ การใช้ข้อมูลดังกล่าวให้น้อยที่สุดเท่าที่จะเป็นไปได้ โดยเฉพาะการค้นหาแบบซ้อน!
ฉันหวังว่าบทความนี้จะเป็นประโยชน์กับการเขียนโปรแกรม Java ของทุกคน