تلخص الأمثلة الواردة في هذه المقالة تقنيات تحسين أداء Java. شاركها مع الجميع لتكون مرجعا لك. التحليل المحدد هو كما يلي:
نشير هنا إلى بعض الكتب وموارد الشبكة المناسبة لمعظم تطبيقات Java.
في برامج JAVA، معظم أسباب مشاكل الأداء لا تكمن في لغة JAVA، بل في البرنامج نفسه. يعد تطوير عادات الترميز الجيدة أمرًا مهمًا للغاية ويمكن أن يؤدي إلى تحسين أداء البرنامج بشكل كبير.
1. حاول استخدام المعدل النهائي.
لا يتم اشتقاق الفئات ذات المعدل النهائي. في واجهة برمجة تطبيقات JAVA الأساسية، هناك العديد من الأمثلة للتطبيق النهائي، مثل java.lang.String. تحديد Final لفئة String يمنع المستخدمين من تجاوز طريقة length() . بالإضافة إلى ذلك، إذا كان الفصل نهائيًا، فإن جميع أساليب الفصل تكون نهائية. سيبحث مترجم Java عن فرص لتضمين جميع الطرق النهائية (يعتمد هذا على تنفيذ المترجم المحدد). وهذا يمكن أن يحسن الأداء بمعدل 50٪.
2. حاول إعادة استخدام الأشياء.
خاصة عند استخدام كائنات السلسلة، يجب استخدام StringBuffer بدلاً من ذلك عند حدوث تسلسل سلسلة، نظرًا لأن النظام لا يتعين عليه قضاء الوقت في إنشاء الكائنات فحسب، بل قد يحتاج أيضًا إلى قضاء بعض الوقت في جمع البيانات المهملة ومعالجتها في المستقبل. لذلك، فإن إنشاء عدد كبير جدًا من الكائنات سيكون له تأثير كبير على أداء البرنامج.
3. حاول استخدام المتغيرات المحلية.
يتم حفظ المعلمات التي تم تمريرها عند استدعاء الطريقة والمتغيرات المؤقتة التي تم إنشاؤها أثناء المكالمة في المكدس (المكدس)، وهو أسرع. يتم إنشاء المتغيرات الأخرى، مثل المتغيرات الثابتة ومتغيرات المثيل وما إلى ذلك، في الكومة وتكون أبطأ.
4. لا تقم بتهيئة المتغيرات بشكل متكرر.
افتراضيًا، عند استدعاء مُنشئ فئة ما، ستقوم Java بتهيئة المتغيرات إلى قيم معينة، ويتم تعيين جميع الكائنات على قيمة خالية، ويتم تعيين المتغيرات الصحيحة على 0، ويتم تعيين المتغيرات العائمة والمزدوجة على 0.0، ويتم تعيين القيم المنطقية على خطأ شنيع. يجب ملاحظة ذلك بشكل خاص عندما يتم اشتقاق فئة من فئة أخرى، لأنه عندما يتم إنشاء كائن باستخدام الكلمة الأساسية الجديدة، سيتم استدعاء جميع المُنشئين في سلسلة المُنشئ تلقائيًا.
هناك ملاحظة هنا عند تعيين القيمة الأولية لمتغير عضو ولكنك تحتاج إلى استدعاء طرق أخرى، فمن الأفضل وضعها في طريقة مثل initXXX()، لأن استدعاء طريقة مباشرة لتعيين قيمة قد يؤدي إلى ظهور قيمة فارغة. استثناء المؤشر لأنه لم تتم تهيئة الفئة public int State = this.getState();
5. في تطوير أنظمة تطبيقات Java+Oracle، يجب أن تكون لغة SQL المضمنة في Java بأحرف كبيرة قدر الإمكان لتقليل عبء التحليل الذي يتحمله محلل Oracle.
6. أثناء عملية برمجة Java، قم بإجراء اتصالات قاعدة البيانات وعمليات دفق الإدخال/الإخراج، بعد الاستخدام، قم بإغلاقها في الوقت المناسب لتحرير الموارد. لأن العمليات على هذه الكائنات الكبيرة سوف تسبب الكثير من الحمل على النظام.
7. سيؤدي الإنشاء المفرط للكائنات إلى استهلاك كمية كبيرة من ذاكرة النظام، وفي الحالات الشديدة، قد يؤدي إلى تسرب الذاكرة، لذلك، من الأهمية بمكان ضمان إعادة تدوير الكائنات منتهية الصلاحية في الوقت المناسب.
إن GC الخاص بـ JVM ليس ذكيًا جدًا، لذا يوصى بتعيينه يدويًا على قيمة خالية بعد استخدام الكائن.
8. عند استخدام آلية المزامنة، حاول استخدام مزامنة الطريقة بدلاً من مزامنة كتلة التعليمات البرمجية.
9. تقليل العد المزدوج للمتغيرات.
على سبيل المثال
ل(int i=0;i<list.size();i++)
ينبغي تعديلها ل
ل(int i=0,len=list.size();i<len;i++)
10. اعتمد استراتيجية الإبداع فقط عندما تحتاج إليها.
على سبيل المثال:
String str="abc";if(i==1){ list.add(str);}
ينبغي تعديلها إلى:
إذا (i==1){String str = "abc"؛ list.add(str);}
11. استخدم الاستثناءات بحذر، لأن الاستثناءات تضر بالأداء.
يؤدي طرح الاستثناء أولاً إلى إنشاء كائن جديد. يستدعي منشئ الواجهة Throwable طريقة محلية تسمى fillInStackTrace() تقوم طريقة fillInStackTrace() بفحص المكدس وجمع معلومات تتبع المكالمات. عندما يتم طرح استثناء، يجب على الجهاز الظاهري ضبط مكدس الاستدعاءات لأنه يتم إنشاء كائن جديد أثناء المعالجة.
يجب استخدام الاستثناءات فقط لمعالجة الأخطاء ولا يجب استخدامها للتحكم في تدفق البرنامج.
12. لا تستخدم عبارات Try/Catch في الحلقات. يجب وضع Try/Catch في المستوى الخارجي للحلقة.
الخطأ هو فئة للحصول على أخطاء النظام، أو أخطاء الجهاز الظاهري. لا يمكن الحصول على كافة استثناءات الأخطاء. إذا أبلغ الجهاز الظاهري عن استثناء خطأ، فلا يمكن الحصول عليه.
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). سيئة للأداء ما لم يكن ذلك ضروريا.
تنطبق نفس القواعد على طريقة الإزالة (int Index)، التي تزيل العنصر في الموضع المحدد في هذا المتجه. انقل جميع العناصر اللاحقة إلى اليسار (قم بتقليل فهرسها بمقدار 1). إرجاع العناصر المحذوفة من هذا المتجه. ولذلك، فإن حذف العنصر الأخير من المتجه أقل تكلفة بكثير من حذف العنصر الأول. من الأفضل استخدام طريقة RemoveAllElements() لإزالة جميع العناصر.
إذا كنت تريد حذف عنصر في المتجه، فيمكنك استخدام Vector.remove(obj); وليس عليك استرداد موضع العنصر بنفسك ثم حذفه، مثل int Index = IndexOf(obj); فِهرِس)؛
15. عند نسخ كميات كبيرة من البيانات، استخدم System.arraycopy();
16. إعادة هيكلة التعليمات البرمجية لزيادة إمكانية قراءة التعليمات البرمجية.
17. قم بإنشاء مثيل لكائن دون استخدام الكلمة الأساسية الجديدة.
عند إنشاء مثيل لفئة باستخدام الكلمة الأساسية الجديدة، يتم استدعاء جميع المنشئين في سلسلة المنشئ تلقائيًا. ولكن إذا كان الكائن يطبق الواجهة القابلة للاستنساخ، فيمكننا استدعاء طريقة clone() الخاصة بها. لا تستدعي طريقة clone () أي منشئي الفئة.
ما يلي هو تنفيذ نموذجي لنمط المصنع.
public static Credit getNewCredit(){ return new Credit();} يستخدم الكود المحسن طريقة clone()، Private static Credit BaseCredit = new Credit(); public static Credit getNewCredit(){ return (Credit)BaseCredit.clone() ;}
18. إذا كان من الممكن استخدام الإزاحة في الضرب والقسمة، فيجب استخدام الإزاحة قدر الإمكان، ولكن من الأفضل إضافة تعليقات، لأن عملية الإزاحة ليست بديهية ويصعب فهمها.
19. لا تعلن عن المصفوفة على أنها: نهائية ثابتة عامة.
20.HaspMap اجتياز.
Map<String, String[]> paraMap = new HashMap<String, String[]>();for( Entry<String, String[]> الإدخال : paraMap.entrySet() ){ String appFieldDefId = input.getKey(); قيم السلسلة [] = الإدخال.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. يعد استخدام القياسات الملموسة أكثر كفاءة من استخدام الواجهات، ولكن يتم تقليل المرونة الهيكلية، ولكن يمكن لـ IDEs الحديثة حل هذه المشكلة.
27. فكر في استخدام الأساليب الثابتة
إذا لم تكن بحاجة إلى الوصول إلى الجزء الخارجي من الكائن، فاجعل طريقتك ثابتة. سيتم استدعاؤه بشكل أسرع لأنه لا يتطلب جدول دليل الوظائف الافتراضية. تعتبر هذه الزميلة أيضًا ممارسة جيدة، لأنها تخبرك بكيفية التمييز بين طبيعة الطريقة، ولن يؤدي استدعاء هذه الطريقة إلى تغيير حالة الكائن.
28. ينبغي تجنب استخدام أساليب GET وSET الجوهرية قدر الإمكان.
في برمجة Android، سيتحمل استدعاء الأساليب الافتراضية الكثير من التكلفة، وهو أكثر تكلفة من استعلام سمات المثيل. يجب علينا فقط استخدام أساليب get وset عند الاستعانة بمصادر خارجية للمكالمات، ولكن عند الاتصال داخليًا، يجب علينا الاتصال بهم مباشرة.
29. تجنب استخدام التعدادات وأرقام الفاصلة العائمة.
30. تشغل المصفوفة ثنائية الأبعاد مساحة ذاكرة أكبر من المصفوفة أحادية البعد، أي حوالي 10 أضعاف الحساب.
31. تقرأ قاعدة بيانات SQLite جميع بيانات الجدول بأكمله بسرعة كبيرة، لكن الاستعلامات الشرطية تستغرق من 30 إلى 50 مللي ثانية. عند القيام بذلك، يجب على الجميع الانتباه إلى استخدامها بأقل قدر ممكن، خاصة عمليات البحث المتداخلة!
آمل أن تكون هذه المقالة مفيدة لبرمجة جافا للجميع.