业务层勿用继承,不要为了方便舍弃了性能。TʌT不好意思我错了
生活随笔
收集整理的這篇文章主要介紹了
业务层勿用继承,不要为了方便舍弃了性能。TʌT不好意思我错了
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
很多人喜歡在action 或service或dao層繼承一些公共的東西 比如jdbc或一些其他的東西 我看過一些小源碼也經常這樣 廢話不多說 直入正題
直入正題前先科普一下TheardLocal類 懂的人直接跳
線程不安全指的是一個帶有類成員變量(狀態)的類的單列被多個線程訪問時才會造成線程不安全,TheardLocal簡單來說就是一個map (線程ID,對象),具體就不多說了,需要詳細了解的請百度。
TheardLocal的出現解決了這一問題,現在很多框架都運用了這個技術,將所有的成員變量都放在TheardLocal內,這樣就不會出現線程安全了,這也是為什么Spring jdbcTemplate的事物管理不會存在多線程安全問題。(你沒發現你所有的注入用的都是這一個單列對象嗎)還有很多很多地方都是這樣的。
現在SpringMvc等使用的是方法及傳慘,方法體有獨自的棧,不存在線程安全,這樣就可以讓你的action無論多少個請求都只實列化一次并且不會造成線程安全。
上面這一段只 為告訴你 減少實例對象 使用單列模式 不然下面的沒必要看了 因為目的就是為了減少實例對象
正題
四個很簡單的java類
[code="java"]public class Animal {
public Animal(){
System.out.println(1);
}
}
[code="java"]public class Dog extends Animal{
}
[code="java"]public class Pig extends Animal{
}
[code="java"]public class Test {
public static void main(String[] args) {
new Dog();
new Pig();
}
}
輸出的肯定是兩個1
這能證明什么呢?
Animal 被實例化了兩次 如果你的項目中action多達100個 甚至1000個 那么這個類被實例化的次數會隨著你的action數量變得越來越多,如果你使用的是單列還好,如果是多列那這個次數就等于 請求數*子類
請使用注入的方式,因為它只是一個對象的引用,10000個引用它在內存中還是那么大。
不要為了那么兩行代碼的方便性影響了性能
使用繼承前先想好它可能會有多少個子類,太多了就用注入,也就多兩行代碼。
樓主目前做的兩個項目中業務層都沒有用過繼承,雖然幾乎每個類都用了jdbc但是都是注入進來的。
實踐驗證真理 額 我承認我錯了 不過也學到很多東西 感謝大家的打擊
下面是我的實踐
第一段
public class Animal {
public void getInfo(){
//一大堆代碼
}
//還可以加N多方法運行結果也一致
}
public class Dog extends Animal{
}
public class Pig {
public Animal animal;
}
第一種運行方式 繼承
public static void main(String[] args) {
Long begin = new Date().getTime();
List<Dog> l = new ArrayList<Dog>();
for (int i = 0; i < 1000000; i++) {
Dog d = new Dog();
l.add(d);//添加到一個集合里避免無引用被垃圾回收
}
Long runTime = new Date().getTime()-begin;
System.out.println(runTime);
}
第二種運行方式 注入
public static void main(String[] args) {
Long begin = new Date().getTime();
List<Pig> l = new ArrayList<Pig>();
Animal animal = new Animal();
for (int i = 0; i < 1000000; i++) {
Pig d = new Pig();
d.animal = animal;
l.add(d);//添加到一個集合里避免無引用被垃圾回收
}
Long runTime = new Date().getTime()-begin;
System.out.println(runTime);
}
兩個運行結果占用內存一致時間幾乎一致
證明一個非靜態方法在內存中只會占一個地址 與靜態的區別在于靜態是系統啟動時分配 非靜態是第一次實例時分配 無論后續實例多少次它只會占用一個內存地址 所以測試時應該獨立啟動運行 不然第二步驟實例Animal類時其實一點時間也沒花內存也沒變
第二段
將Animal類添加一個非靜態成員變量
public Integer age = new Integer(10);
兩個運行結果 第二種運行時間內存占用比第一種小一倍
證明一個類在實例化的時候會為成員變量分配內存空間 而方法不會
第三段
將Animal類添加一個方法引用age
與第二段一致
證明方法在使用成員變量時只是引用不是復制
第四段
將Animal類添加一個構造函數
public Animal(){
//打印
}
注入的方式構造函數運行一次
繼承的方式隨子類實例次數
最后總結
1一個類在實例化時
非靜態并且有值的成員變量(int long String這些類型在不使用構造傳參時 如果參數一致在內存中也會存在一個)會在分配在內存中 以后每次實例也都會
非靜態方法只會在第一次實例化時分配 以后每次的實例都只是引用
2父類在很多子類繼承時構造函數不要過于復雜,因為構造函數在每次實例化時都會運行一次
3一個類如果構造函數是空并且也沒有非靜態不為空的成員變量那么
new 一個類一百次 和new一個類一次 加100此空循環 無論內存占用還是速度都一致?
直入正題前先科普一下TheardLocal類 懂的人直接跳
線程不安全指的是一個帶有類成員變量(狀態)的類的單列被多個線程訪問時才會造成線程不安全,TheardLocal簡單來說就是一個map (線程ID,對象),具體就不多說了,需要詳細了解的請百度。
TheardLocal的出現解決了這一問題,現在很多框架都運用了這個技術,將所有的成員變量都放在TheardLocal內,這樣就不會出現線程安全了,這也是為什么Spring jdbcTemplate的事物管理不會存在多線程安全問題。(你沒發現你所有的注入用的都是這一個單列對象嗎)還有很多很多地方都是這樣的。
現在SpringMvc等使用的是方法及傳慘,方法體有獨自的棧,不存在線程安全,這樣就可以讓你的action無論多少個請求都只實列化一次并且不會造成線程安全。
上面這一段只 為告訴你 減少實例對象 使用單列模式 不然下面的沒必要看了 因為目的就是為了減少實例對象
正題
四個很簡單的java類
[code="java"]public class Animal {
public Animal(){
System.out.println(1);
}
}
[code="java"]public class Dog extends Animal{
}
[code="java"]public class Pig extends Animal{
}
[code="java"]public class Test {
public static void main(String[] args) {
new Dog();
new Pig();
}
}
輸出的肯定是兩個1
這能證明什么呢?
Animal 被實例化了兩次 如果你的項目中action多達100個 甚至1000個 那么這個類被實例化的次數會隨著你的action數量變得越來越多,如果你使用的是單列還好,如果是多列那這個次數就等于 請求數*子類
請使用注入的方式,因為它只是一個對象的引用,10000個引用它在內存中還是那么大。
不要為了那么兩行代碼的方便性影響了性能
使用繼承前先想好它可能會有多少個子類,太多了就用注入,也就多兩行代碼。
樓主目前做的兩個項目中業務層都沒有用過繼承,雖然幾乎每個類都用了jdbc但是都是注入進來的。
實踐驗證真理 額 我承認我錯了 不過也學到很多東西 感謝大家的打擊
下面是我的實踐
第一段
public class Animal {
public void getInfo(){
//一大堆代碼
}
//還可以加N多方法運行結果也一致
}
public class Dog extends Animal{
}
public class Pig {
public Animal animal;
}
第一種運行方式 繼承
public static void main(String[] args) {
Long begin = new Date().getTime();
List<Dog> l = new ArrayList<Dog>();
for (int i = 0; i < 1000000; i++) {
Dog d = new Dog();
l.add(d);//添加到一個集合里避免無引用被垃圾回收
}
Long runTime = new Date().getTime()-begin;
System.out.println(runTime);
}
第二種運行方式 注入
public static void main(String[] args) {
Long begin = new Date().getTime();
List<Pig> l = new ArrayList<Pig>();
Animal animal = new Animal();
for (int i = 0; i < 1000000; i++) {
Pig d = new Pig();
d.animal = animal;
l.add(d);//添加到一個集合里避免無引用被垃圾回收
}
Long runTime = new Date().getTime()-begin;
System.out.println(runTime);
}
兩個運行結果占用內存一致時間幾乎一致
證明一個非靜態方法在內存中只會占一個地址 與靜態的區別在于靜態是系統啟動時分配 非靜態是第一次實例時分配 無論后續實例多少次它只會占用一個內存地址 所以測試時應該獨立啟動運行 不然第二步驟實例Animal類時其實一點時間也沒花內存也沒變
第二段
將Animal類添加一個非靜態成員變量
public Integer age = new Integer(10);
兩個運行結果 第二種運行時間內存占用比第一種小一倍
證明一個類在實例化的時候會為成員變量分配內存空間 而方法不會
第三段
將Animal類添加一個方法引用age
與第二段一致
證明方法在使用成員變量時只是引用不是復制
第四段
將Animal類添加一個構造函數
public Animal(){
//打印
}
注入的方式構造函數運行一次
繼承的方式隨子類實例次數
最后總結
1一個類在實例化時
非靜態并且有值的成員變量(int long String這些類型在不使用構造傳參時 如果參數一致在內存中也會存在一個)會在分配在內存中 以后每次實例也都會
非靜態方法只會在第一次實例化時分配 以后每次的實例都只是引用
2父類在很多子類繼承時構造函數不要過于復雜,因為構造函數在每次實例化時都會運行一次
3一個類如果構造函數是空并且也沒有非靜態不為空的成員變量那么
new 一個類一百次 和new一個類一次 加100此空循環 無論內存占用還是速度都一致?
轉載于:https://www.cnblogs.com/shhaoran/archive/2013/02/04/2924524.html
總結
以上是生活随笔為你收集整理的业务层勿用继承,不要为了方便舍弃了性能。TʌT不好意思我错了的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 美国巨头ins全面效仿TikTok引用户
- 下一篇: 面积超100个足球场 国内唯一高寒地区自