綠色運輸衝一波 城市的規劃與挑戰

文:詹詒絜(台達電子文教基金會高級專員)

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※為什麼 USB CONNECTOR 是電子產業重要的元件?

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※台北網頁設計公司全省服務真心推薦

※想知道最厲害的網頁設計公司"嚨底家"!

※推薦評價好的iphone維修中心

Quartz.Net系列(七):Trigger之SimpleScheduleBuilder詳解

所有方法圖

 

 SimpleScheduleBuilder方法

RepeatForever:指定觸發器將無限期重複。

WithRepeatCount:指定重複次數

var trigger = TriggerBuilder.Create().WithSimpleSchedule(s=>s.WithIntervalInSeconds(1).RepeatForever()).Build();

 

            var trigger = TriggerBuilder.Create().WithSimpleSchedule(s=>s.WithIntervalInSeconds(1)
                                                                         .WithRepeatCount(10)).Build();

 

注:底層實現是repeatCount+1,也就是總共執行repeatCount+1次

        /// <summary>
        /// Specify a the number of time the trigger will repeat - total number of
        /// firings will be this number + 1.
        /// </summary>
        /// <remarks>
        /// </remarks>
        /// <param name="repeatCount">the number of seconds at which the trigger should repeat.</param>
        /// <returns>the updated SimpleScheduleBuilder</returns>
        /// <seealso cref="ISimpleTrigger.RepeatCount" />
        /// <seealso cref="RepeatForever" />
        public SimpleScheduleBuilder WithRepeatCount(int repeatCount)
        {
            this.repeatCount = repeatCount;
            return this;
        }

 

 

WithInterval:以毫秒為單位指定重複間隔,由於是TimeSpan也可以指定時分秒

WithIntervalInHours:以小時為單位指定重複間隔

WithIntervalInMinutes:以分鐘單位指定重複間隔

WithIntervalInSeconds:以秒為單位指定重複間隔

            var trigger = TriggerBuilder.Create().WithSimpleSchedule(s=>s .WithIntervalInSeconds(1)
                                                                          .WithInterval(TimeSpan.FromDays(1))
                                                                          .WithIntervalInMinutes(1)
                                                                          .WithIntervalInHours(1)
                                                                          .WithRepeatCount(5))
                                                 .Build();

注:底層都是通過WithInterval實現的

        /// <summary>
        /// Specify a repeat interval in milliseconds.
        /// </summary>
        /// <remarks>
        /// </remarks>
        /// <param name="timeSpan">the time span at which the trigger should repeat.</param>
        /// <returns>the updated SimpleScheduleBuilder</returns>
        /// <seealso cref="ISimpleTrigger.RepeatInterval" />
        /// <seealso cref="WithRepeatCount(int)" />
        public SimpleScheduleBuilder WithInterval(TimeSpan timeSpan)
        {
            interval = timeSpan;
            return this;
        }

        /// <summary>
        /// Specify a repeat interval in seconds.
        /// </summary>
        /// <remarks>
        /// </remarks>
        /// <param name="seconds">the time span at which the trigger should repeat.</param>
        /// <returns>the updated SimpleScheduleBuilder</returns>
        /// <seealso cref="ISimpleTrigger.RepeatInterval" />
        /// <seealso cref="WithRepeatCount(int)" />
        public SimpleScheduleBuilder WithIntervalInSeconds(int seconds)
        {
            return WithInterval(TimeSpan.FromSeconds(seconds));
        }

靜態方法:

RepeatMinutelyForever

RepeatMinutelyForTotalCount

RepeatSecondlyForever

RepeatSecondlyForTotalCount

RepeatHourlyForever

RepeatHourlyForTotalCount

var trigger = TriggerBuilder.Create().WithSchedule(SimpleScheduleBuilder.RepeatSecondlyForTotalCount(2)).Build();

 

 /// <summary>
        /// Create a SimpleScheduleBuilder set to repeat forever with a 1 minute interval.
        /// </summary>
        /// <remarks>
        /// </remarks>
        /// <returns>the new SimpleScheduleBuilder</returns>
        public static SimpleScheduleBuilder RepeatMinutelyForever()
        {
            SimpleScheduleBuilder sb = Create()
                .WithInterval(TimeSpan.FromMinutes(1))
                .RepeatForever();

            return sb;
        }

        /// <summary>
        /// Create a SimpleScheduleBuilder set to repeat forever with an interval
        /// of the given number of minutes.
        /// </summary>
        /// <remarks>
        /// </remarks>
        /// <returns>the new SimpleScheduleBuilder</returns>
        public static SimpleScheduleBuilder RepeatMinutelyForever(int minutes)
        {
            SimpleScheduleBuilder sb = Create()
                .WithInterval(TimeSpan.FromMinutes(minutes))
                .RepeatForever();

            return sb;
        }

        /// <summary>
        /// Create a SimpleScheduleBuilder set to repeat forever with a 1 second interval.
        /// </summary>
        /// <remarks>
        /// </remarks>
        /// <returns>the new SimpleScheduleBuilder</returns>
        public static SimpleScheduleBuilder RepeatSecondlyForever()
        {
            SimpleScheduleBuilder sb = Create()
                .WithInterval(TimeSpan.FromSeconds(1))
                .RepeatForever();

            return sb;
        }

        /// <summary>
        /// Create a SimpleScheduleBuilder set to repeat forever with an interval
        /// of the given number of seconds.
        /// </summary>
        /// <remarks>
        /// </remarks>
        /// <returns>the new SimpleScheduleBuilder</returns>
        public static SimpleScheduleBuilder RepeatSecondlyForever(int seconds)
        {
            SimpleScheduleBuilder sb = Create()
                .WithInterval(TimeSpan.FromSeconds(seconds))
                .RepeatForever();

            return sb;
        }

        /// <summary>
        /// Create a SimpleScheduleBuilder set to repeat forever with a 1 hour interval.
        /// </summary>
        /// <remarks>
        /// </remarks>
        /// <returns>the new SimpleScheduleBuilder</returns>
        public static SimpleScheduleBuilder RepeatHourlyForever()
        {
            SimpleScheduleBuilder sb = Create()
                .WithInterval(TimeSpan.FromHours(1))
                .RepeatForever();

            return sb;
        }

        /// <summary>
        /// Create a SimpleScheduleBuilder set to repeat forever with an interval
        /// of the given number of hours.
        /// </summary>
        /// <remarks>
        /// </remarks>
        /// <returns>the new SimpleScheduleBuilder</returns>
        public static SimpleScheduleBuilder RepeatHourlyForever(int hours)
        {
            SimpleScheduleBuilder sb = Create()
                .WithInterval(TimeSpan.FromHours(hours))
                .RepeatForever();

            return sb;
        }

        /// <summary>
        /// Create a SimpleScheduleBuilder set to repeat the given number
        /// of times - 1  with a 1 minute interval.
        /// </summary>
        /// <remarks>
        /// <para>Note: Total count = 1 (at start time) + repeat count</para>
        /// </remarks>
        /// <returns>the new SimpleScheduleBuilder</returns>
        public static SimpleScheduleBuilder RepeatMinutelyForTotalCount(int count)
        {
            if (count < 1)
            {
                throw new ArgumentException("Total count of firings must be at least one! Given count: " + count);
            }

            SimpleScheduleBuilder sb = Create()
                .WithInterval(TimeSpan.FromMinutes(1))
                .WithRepeatCount(count - 1);

            return sb;
        }

        /// <summary>
        /// Create a SimpleScheduleBuilder set to repeat the given number
        /// of times - 1  with an interval of the given number of minutes.
        /// </summary>
        /// <remarks>
        /// <para>Note: Total count = 1 (at start time) + repeat count</para>
        /// </remarks>
        /// <returns>the new SimpleScheduleBuilder</returns>
        public static SimpleScheduleBuilder RepeatMinutelyForTotalCount(int count, int minutes)
        {
            if (count < 1)
            {
                throw new ArgumentException("Total count of firings must be at least one! Given count: " + count);
            }

            SimpleScheduleBuilder sb = Create()
                .WithInterval(TimeSpan.FromMinutes(minutes))
                .WithRepeatCount(count - 1);

            return sb;
        }

        /// <summary>
        /// Create a SimpleScheduleBuilder set to repeat the given number
        /// of times - 1  with a 1 second interval.
        /// </summary>
        /// <remarks>
        /// <para>Note: Total count = 1 (at start time) + repeat count</para>
        /// </remarks>
        /// <returns>the new SimpleScheduleBuilder</returns>
        public static SimpleScheduleBuilder RepeatSecondlyForTotalCount(int count)
        {
            if (count < 1)
            {
                throw new ArgumentException("Total count of firings must be at least one! Given count: " + count);
            }

            SimpleScheduleBuilder sb = Create()
                .WithInterval(TimeSpan.FromSeconds(1))
                .WithRepeatCount(count - 1);

            return sb;
        }

        /// <summary>
        /// Create a SimpleScheduleBuilder set to repeat the given number
        /// of times - 1  with an interval of the given number of seconds.
        /// </summary>
        /// <remarks>
        /// <para>Note: Total count = 1 (at start time) + repeat count</para>
        /// </remarks>
        /// <returns>the new SimpleScheduleBuilder</returns>
        public static SimpleScheduleBuilder RepeatSecondlyForTotalCount(int count, int seconds)
        {
            if (count < 1)
            {
                throw new ArgumentException("Total count of firings must be at least one! Given count: " + count);
            }

            SimpleScheduleBuilder sb = Create()
                .WithInterval(TimeSpan.FromSeconds(seconds))
                .WithRepeatCount(count - 1);

            return sb;
        }

        /// <summary>
        /// Create a SimpleScheduleBuilder set to repeat the given number
        /// of times - 1  with a 1 hour interval.
        /// </summary>
        /// <remarks>
        /// <para>Note: Total count = 1 (at start time) + repeat count</para>
        /// </remarks>
        /// <returns>the new SimpleScheduleBuilder</returns>
        public static SimpleScheduleBuilder RepeatHourlyForTotalCount(int count)
        {
            if (count < 1)
            {
                throw new ArgumentException("Total count of firings must be at least one! Given count: " + count);
            }

            SimpleScheduleBuilder sb = Create()
                .WithInterval(TimeSpan.FromHours(1))
                .WithRepeatCount(count - 1);

            return sb;
        }

        /// <summary>
        /// Create a SimpleScheduleBuilder set to repeat the given number
        /// of times - 1  with an interval of the given number of hours.
        /// </summary>
        /// <remarks>
        /// <para>Note: Total count = 1 (at start time) + repeat count</para>
        /// </remarks>
        /// <returns>the new SimpleScheduleBuilder</returns>
        public static SimpleScheduleBuilder RepeatHourlyForTotalCount(int count, int hours)
        {
            if (count < 1)
            {
                throw new ArgumentException("Total count of firings must be at least one! Given count: " + count);
            }

            SimpleScheduleBuilder sb = Create()
                .WithInterval(TimeSpan.FromHours(hours))
                .WithRepeatCount(count - 1);

            return sb;
        }

 

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※為什麼 USB CONNECTOR 是電子產業重要的元件?

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※台北網頁設計公司全省服務真心推薦

※想知道最厲害的網頁設計公司"嚨底家"!

※推薦評價好的iphone維修中心

石油公司看好電動車,預測2030年石油需求逐下滑

隨著相關技術逐漸成熟,如今已經不再只有相關業者看好電動車市場,就連石油大廠道達爾(Total)近日都承認,在這樣的發展下,石油的需求可能即將見頂,未來電動車的商機將不容小覷。

彭博社報導,道達爾的能源經濟學家Joel Couse 表示,隨著電動車市場持續擴大,估計至2030 年時,電動車將佔有新車市場15~30%,石油需求預計將在屆時達到頂峰,之後就不會再出現增長,甚至可能逐漸下滑。

這樣的話從石油主要生產商的口中說出有些令人感到意外,就連彭博新能源財經(BNEF)的主管Colin McKerracher 都表示,道達爾的分析是目前為止最看好電動車產業的預測,甚至超過彭博的預估值。

其實不只是道達爾,荷蘭皇家殼牌(Shell)也已經開始削減石油需求的長期預測。為了因應未來科技的走向,殼牌已經建立一個全新業務部門,針對多種綠能可能造成的經濟效益進行分析。

彭博新能源財經指出,在電動車的製程中,電池是成本中最昂貴的部分,幾乎可以佔到總成本的一半,高昂的成本價格也是造成許多車商在發展電動車時,會選擇高價車款為主打的原因。

然而隨著科技持續發展,電池價格開始逐年下降、效能持續提升,電動車已經開始能與燃油車在價格及性能上做競爭。儘管在全球汽車銷量中,電動車目前僅佔有約1% 的市場,但許多車商已經注意到這個趨勢,開始投入數十億美元進入電動車市場耕耘。

除了開始進入電動車市場的捷豹(Jaguar)、富豪(Volvo)之外,賓士(Mercedes-Benz)、通用(General)及許多車廠也將在2020 年時推出數十種電動車款,豐田(Toyota)更計劃在2050 年時,淘汰所有燃油車款,汽車市場「雪崩式」改變的時刻即將來到。

彭博新能源財經負責人Michael Liebreich 認為,至2020 年時,將會有120 種以上不同型號的電動車在市面上供消費者選擇,「到了那個時候,燃油車會變成很過時的東西。」 

(合作媒體:。圖片出處:publidc domain CC0)

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※為什麼 USB CONNECTOR 是電子產業重要的元件?

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※台北網頁設計公司全省服務真心推薦

※想知道最厲害的網頁設計公司"嚨底家"!

※推薦評價好的iphone維修中心

和通用競爭,Ford推首全電動車CUV

目前福特所販售的電動車皆為「合規車(compliance cars)」,也就是各大車廠為了符合美國州政府零排放規定而以一般汽車為基底改造而成的電動車。近日,福特技術長Raj Nair 表示他們將於2020 年推出首款全電動車,這款電動車將進行量產且定價相對低廉。

福特進入電動車市場的時間點明顯晚於其主要競爭對手—通用汽車。通用汽車已推出價格優惠又續航力充足的Chevy Bolt 電動車,而福特將「以量取勝」。Nair 在Business Insider 的訪問中強調,「這將是一款大眾化的電動車,我們必須同時達成高續航力與價格實惠的目標,否則這只會是一款瞄準小眾市場的奢侈品。」

這款交叉型(CUV)全電動車將於2020 年推出,Nair 保證福特的全電動車將以充電一次行駛超過480 公里的續航力以及交叉型車款的多功能特性來取得市場青睞。在交叉型與小型SUV 車款方面,Tesla 將於2019 至2020 年間推出Model Y。

除了這款全電動車之外,福特也承認他們正計畫推出其他類似的車款,但多半為油電混合車。這款電動車將於福特Flat Rock 工廠進行生產,並在2020 年於北美、歐洲與亞洲推出。

(合作媒體:。圖片出處:Ford Europe)

 

首圖來源:Ford Europe)

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※為什麼 USB CONNECTOR 是電子產業重要的元件?

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※台北網頁設計公司全省服務真心推薦

※想知道最厲害的網頁設計公司"嚨底家"!

※推薦評價好的iphone維修中心

打個總結:Web性能優化

前段時間優化一個公司歷史老項目的Web性能,卻引出了一系列的問題,讓我反思良多。
我通過Chrome的Lighthouse工具可以看出一些性能參數和問題反饋,我逐一對其進行優化。
根據資源請求的不同,大致可以分為前端資源性能和後端程序性能兩個方面。
先分析一下前端資源吧:

  1. Defer offscreen images。

Chrome給出的建議是:

Consider lazy-loading offscreen and hidden images after all critical resources have finished loading to lower time to interactive. Learn more.

意思是可以考慮延遲加載一些圖片或者隱藏一些圖片在所有關鍵資源完成加載后再考慮加載,通過延遲加載來降低交互時間。
lazy-load的實現方法很多,開源框架推薦:lazysizes。
當然也可以使用npm方式安裝:

npm install lazysizes
使用方式很簡單,先引入lazysize到需要的頁面:

<script src="lazysizes.min.js" async=""></script>

然後給需要被lazyload的img標籤上加新的屬性,如下:

<img
    data-sizes="auto"
    data-src="image2.jpg"
    data-srcset="image1.jpg 300w,
    image2.jpg 600w,
    image3.jpg 900w" class="lazyload" />

特別要注意,有時候太多background方式加載的圖片也會影響性能,lazysizes也可以處理這樣的圖片。方法如下,使用data-bg屬性即可:

<div class="lazyload" data-bg="/path/to/image.jpg"></div>
  1. Reduce JavaScript execution time

解決這個問題方法很多,第一個想到的就是壓縮資源。
比如壓縮js和css文件,可以考慮使用webpack工具或者gulp來壓縮大資源文件,合併一些文件資源請求。
還可以通過預加載來提高響應速度,可以在最重要的js資源文件的引入上加入預加載,代碼如下:

<link rel="preload" as="style" href="css/style.css">

通過增加preload
最後還可以異步加載資源,異步不會阻塞主進程,代碼調整也很小:

<script src="xxx" async></script>

除此之外JavaScript的執行時間過長還有可能是有大量邏輯運算,有很多頁面把一些邏輯判斷和計算都交給前端去計算,這樣也不利於渲染,建議還是把複雜邏輯和計算盡可能交給後端去處理,讓前端渲染更加“輕量”。
3. Backend response
數據接口返回有時候也很拖累響應時間,因為一些前端結構需要根據返回的數據進行組裝新的頁面結構。
這裏可以考慮找到性能真正的瓶頸,到底是數據庫查詢導致的慢,還是業務邏輯不清晰導致的冗餘,或者其他原因。
我遇到的是因為老項目的數據庫操作類不是單例,會每次產生一個數據庫連接句柄,且該頁面複雜又多的sql查詢。
我勇敢地修改着10多年歷史的代碼,編寫了單例模式的操作類,然後增加了必要的緩存機制。
然而後面我遇到了問題,首先單例類在一些特殊情形下不滿足之前的代碼需求,導致奇特的數據庫報錯,而async屬性導致一些js文件無法同步加載到位,而有一些依賴這些資源的php文件執行報錯。
最終在同事的幫助下,恢復了服務,我也再一次體會到了任何一種性能提升都要謹慎,特別是對一個古老的項目。
前人不敢動的代碼,可能是深淵。

PS:我的公眾號 成都有娃兒會同步發布該文章,也可以關注哦!

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※為什麼 USB CONNECTOR 是電子產業重要的元件?

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※台北網頁設計公司全省服務真心推薦

※想知道最厲害的網頁設計公司"嚨底家"!

新北清潔公司,居家、辦公、裝潢細清專業服務

※推薦評價好的iphone維修中心

【案例演示】JVM之強引用、軟引用、弱引用、虛引用

1.背景

想要理解對象什麼時候回收,就要理解到對象引用這個概念,於是有了下文

2.java中引用對象結構圖

3.引用詳解

3.1.什麼是強引用

a.當內存不足,JVM開始垃圾回收,對於強引用的對象,就算是出現了00M也不會對該對象進行回收,死都不收。

b.強引用是我們最常見的普通對象引用,只要還有強引用指向一個對象,就能表明對象還“活着”,垃圾收集器不會碰這種對象。

在Java中最常見的就是強引用,把一個對象賦給一個引用變量,這個引用變量就是一個強引用。

當一個對象被強引用變量引用時,它處於可達狀態,它是不可能被垃圾回收機制回收的,即使該對象以後永遠都不會被用到JVM也不會回收。

因此強引用是造成Java內存泄漏的主要原因之一

c.對於一個普通的對象,如果沒有其他的引用關係,只要超過了引用的作用域或者顯式地將相應(強)引用賦值為null,一般認為就是可以被垃圾收集的了〈當然具體回收時機還是要看垃圾收集策略)。

案例:

package com.wfd360.demo03GC.referDemo;

/**
 * @author 姿勢帝-博客園
 * @address https://www.cnblogs.com/newAndHui/
 * @WeChat 851298348
 * @create 06/20 12:12
 * @description
 */
public class StrongRefer {
    /**
     * 強引用的理解
     *
     * @param args
     */
    public static void main(String[] args) {
        Object obj1 = new Object();
        // 建立強引用
        Object obj2 = obj1;
        // 觀察obj1 和 obj2 的各種內存地址
        System.out.println("obj1=" + obj1);
        System.out.println("obj2=" + obj2);
        // obj1創建可以回收的條件
        obj1 = null;
        // gc回收
        System.gc();
        // 觀察各對象情況
        System.out.println("obj1=" + obj1);
        System.out.println("obj2=" + obj2);
    }
}

View Code

 從測試結果課程看出,obj1的實際對象別沒有回收;

3.2.什麼是軟引用

a.軟引用是用來描述一些還有用但並非必需的對象,需要用java.lang.ref.SoftReference類來實現。

b.對於軟引用關聯着的對象,在系統將要發生內存溢出異常之前,將會把這些對象列進回收範圍之中進行第二次回收。如果這次回收還沒有足夠的內存,才會拋出內存溢出異常。在JDK1.2之後,提供了Soft Reference類來實現軟引用。

c.軟引用通常用在對內存敏感的程序中,比如高速緩存就有用到軟引用,內存夠用的時候就保留,不夠用就回收!

案例:

package com.wfd360.demo03GC.referDemo;

import java.lang.ref.SoftReference;

/**
 * @author 姿勢帝-博客園
 * @address https://www.cnblogs.com/newAndHui/
 * @WeChat 851298348
 * @create 06/20 12:12
 * @description
 */
public class SoftRefer {

    /**
     * 軟引用的理解
     * 通過設置jvm參數,在不同的條件下觀察
     *
     * @param -Xms5m -Xmx5m -XX:+PrintGCDetails
     * @param args
     */
    public static void main(String[] args) {
        // 測試內存充足(不回收軟引用)
        //testSoftReferNOGc();
        // 測試內存不充足(回收軟引用)
        testSoftReferGc();
    }

    /**
     * 模擬內存充足的情況
     */
    public static void testSoftReferNOGc() {
        Object obj1 = new Object();
        // 建立軟引用
        SoftReference softRefer = new SoftReference<>(obj1);
        // 觀察內存地址
        System.out.println("obj1=" + obj1);
        System.out.println("softRefer=" + softRefer.get());
        // obj1創建可以回收的條件
        obj1 = null;
        // gc回收
        System.gc();
        // 再次觀察內存地址
        System.out.println("obj1=" + obj1);
        System.out.println("softRefer=" + softRefer.get());
    }

    /**
     * 模擬內存不足
     * 1.設置較小的堆內存
     * 2.創建大對象
     * 3.jvm參
     * -Xms5m -Xmx5m -XX:+PrintGCDetails
     */
    public static void testSoftReferGc() {
        Object obj1 = new Object();
        // 建立軟引用
        SoftReference softRefer = new SoftReference<>(obj1);
        // 觀察內存地址
        System.out.println("obj1=" + obj1);
        System.out.println("softRefer=" + softRefer.get());
        // obj1創建可以回收的條件
        obj1 = null;
        try {
            byte[] bytes = new byte[6 * 1024 * 1024];
        } catch (Throwable e) {
            System.out.println("===============>error:" + e.getMessage());
        } finally {
            // 再次觀察內存地址
            System.out.println("obj1=" + obj1);
            System.out.println("softRefer=" + softRefer.get());
        }
    }
}

View Code

內存充足測試結果:

 內存不充足測試結果:

 實際案例

假如有一個應用需要讀取大量的本地數據(圖片、通訊率、臨時文件等):

如果每次讀取數據都從硬盤讀取則會嚴重影響性能,

如果一次性全部加載到內存中又可能造成內存溢出。

此時使用軟引用可以解決這個問題。

設計思路是:用一個HashMap來保存數據的路徑和相應數據對象關聯的軟引用之間的映射關係,在內存不足時,

JVM會自動回收這些緩存數據對象所佔用的空間,從而有效地避免了00M的問題。

Map<String,SoftReference>imageCache=new HashMap<String,SoftReference>();

 3.3.什麼是弱引用

a.弱引用也是用來描述非必需對象的,但是它的強度比軟引用更弱一些,被弱引用關聯的對象只能生存到下一次垃圾收集發生之前。

b..當垃圾收集器工作時,無論當前內存是否足夠,都會回收掉只被弱引用關聯的對象。在JDK1.2之後,提供廣Weak Reference類來實現弱引用。

c.弱引用需要用Java.lang.ref.WeakReference類來實現,它比軟引用的生存期更短.

案例:

package com.wfd360.demo03GC.referDemo;

import java.lang.ref.WeakReference;

/**
 * @author 姿勢帝-博客園
 * @address https://www.cnblogs.com/newAndHui/
 * @WeChat 851298348
 * @create 06/20 12:12
 * @description
 */
public class WeakRefer {

    /**
     * 弱引用的理解
     *
     * @param args
     */
    public static void main(String[] args) {
        Object obj1 = new Object();
        // 建立弱引用
        WeakReference softRefer = new WeakReference<>(obj1);
        // 觀察內存地址
        System.out.println("obj1=" + obj1);
        System.out.println("softRefer=" + softRefer.get());
        // obj1創建可以回收的條件
        obj1 = null;
        // gc回收
        System.gc();
        // 再次觀察內存地址
        System.out.println("obj1=" + obj1);
        System.out.println("softRefer=" + softRefer.get());
    }

}

View Code

 擴展知識-WeakHashMap

查看API介紹:

 測試代碼:

package com.wfd360.demo03GC.referDemo;

import java.util.HashMap;
import java.util.WeakHashMap;

/**
 * @author 姿勢帝-博客園
 * @address https://www.cnblogs.com/newAndHui/
 * @WeChat 851298348
 * @create 06/20 5:10
 * @description <p>
 * 弱引用引用之:WeakHashMap
 * 以弱鍵 實現的基於哈希表的 Map。在 WeakHashMap 中,當某個鍵不再正常使用時,將自動移除其條目。
 * 更精確地說,對於一個給定的鍵,其映射的存在並不阻止垃圾回收器對該鍵的丟棄,這就使該鍵成為可終止的,被終止,
 * 然後被回收。丟棄某個鍵時,其條目從映射中有效地移除,因此,該類的行為與其他的 Map 實現有所不同。
 * </p>
 */
public class WeakReferMap {
    /**
     * 測試 HashMap 與 WeakHashMap 區別
     * 測試邏輯:
     * 1.創建不同的map
     * 2.創建key  value值
     * 3.放入各自的map,並打印結果
     * 4.將key設置為null,並打印結果
     * 5.手動GC,並打印結果
     *
     * @param args
     */
    public static void main(String[] args) {
        hashMapMethod();
        System.out.println("--------華麗的分割線--------");
        weakHashMapMethod();
    }

    /**
     * HashMap測試(強引用)
     */
    private static void hashMapMethod() {
        HashMap<String, String> map = new HashMap<>();
        String key = "key1";
        String value = "HashMap-value";

        map.put(key, value);
        System.out.println(map);

        key = null;
        System.out.println(map);

        System.gc();
        System.out.println(map);
    }

    /**
     * 若引用(WeakHashMap測試)
     */
    private static void weakHashMapMethod() {
        WeakHashMap<String, String> map = new WeakHashMap<>();
        // 注意這裏的new一個字符串與直接寫key="key2"對測試結果是有區別的,詳細原因可以看之前講的內存分配
        String key = new String("key2");
        String value = "WeakHashMap-value";

        map.put(key, value);
        System.out.println(map);

        key = null;
        System.out.println(map);

        System.gc();
        System.out.println(map);

    }

}

View Code

測試結果:

 從測試結果可以看出:弱引用的map數據已經被回收。

 擴展知識-ReferenceQueue引用隊列

 代碼:

package com.wfd360.demo03GC.referDemo;

import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;

/**
 * @author 姿勢帝-博客園
 * @address https://www.cnblogs.com/newAndHui/
 * @WeChat 851298348
 * @create 06/20 7:23
 * @description
 */
public class QueueRefer {
    /**
     * 測試弱引用回收前,把數據放入隊列中
     *
     * @param args
     * @throws InterruptedException
     */
    public static void main(String[] args) throws InterruptedException {
        Object obj1 = new Object();
        ReferenceQueue<Object> referenceQueue = new ReferenceQueue();
        // 當GC釋放對象內存的時候,會將引用加入到引用隊列
        WeakReference<Object> weakReference = new WeakReference<>(obj1, referenceQueue);

        System.out.println(obj1);
        System.out.println(weakReference.get());
        System.out.println(referenceQueue.poll());

        System.out.println("--------華麗的分割線--------");
        obj1 = null;
        System.gc();
        Thread.sleep(500);

        System.out.println(obj1);
        System.out.println(weakReference.get());
        System.out.println(referenceQueue.poll());
    }

}

View Code

採用弱引用的方式測試結果:

從測試結果可以看出,需要回收的對象已經進入隊列。

 採用軟引用的方式測試結果:

 從測試結果可以看出,軟引用,沒有到達回收的條件,並沒有進行回收,也不會進入隊列;

3.4.什麼是虛引用

1.虛引用需要java.lang.ref.PhantomReference類來實現。

2.與其他幾種引用都不同,虛引用並不會決定對象的生命周期。如果一個對象僅持有

虛引用,那麼它就和沒有任何引用一樣,在任何時候都可能被垃圾回收器回收,它不能單獨使用也不能通過它訪

問對象,虛引用必須和引用隊列(ReferenceQueue)聯合使用。

3.虛引用的主要作用是跟蹤對象被垃圾回收的狀態。僅僅是提供了一種確保對象被finalize以後,做某些事情的

機制。PhantomReference的get方法總是返回null,因此無法訪問對應的引用對象。其意義在於說明一個對象己

經進入俑finalization階段,可以被gc回收,用來實現比finalization機制更靈活的回收操作。

4.設置虛引用關聯的唯一目的,就是在這個對象被收集器回收的時候收到一個系統通知或者後續添加

進一步的處理。Java技術允許使用finalize()方法在垃圾收集器將對象從內存中清除出去之前做必要的清理工作。

代碼:

package com.wfd360.demo03GC.referDemo;

import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;

/**
 * @author 姿勢帝-博客園
 * @address https://www.cnblogs.com/newAndHui/
 * @WeChat 851298348
 * @create 06/20 7:44
 * @description
 */
public class PhantomRefer {
    /**
     * 虛引用測試
     * @param args
     * @throws InterruptedException
     */
    public static void main(String[] args) throws InterruptedException {
        Object obj1 = new Object();
        ReferenceQueue<Object> referenceQueue = new ReferenceQueue();
        PhantomReference<Object> phantomReference = new PhantomReference<>(obj1,referenceQueue);

        System.out.println(obj1);
        System.out.println(phantomReference.get());
        System.out.println(referenceQueue.poll());

        System.out.println("--------華麗的分割線--------");

        obj1 = null;
        System.gc();
        Thread.sleep(500);

        System.out.println(obj1);
        System.out.println(phantomReference.get());
        System.out.println(referenceQueue.poll());
    }

}

View Code

測試結果:

4.重要總結

對象是否存活判斷流程:

1.可達性分析,看是否有GC Roots的引用鏈,如果沒有將做第一次標記;

2.檢查是否需要執行finalize()方法,

如果沒必要(之前執行過了),直接回收內存;

如果要執行finalize()方法,這個時候對象如果再次建立引用鏈(唯一自救機會),對象不會被回收,否則直接回收;

總結:

1.對象回收滿足兩個條件:

a.沒有引用鏈。

b.回收前會執行finalize()方法,如果執行finalize(),沒有再次建立連接(如果重新與引用鏈上的任意對象建立連接,例如給對象賦值,該對象都不會被回收)

2.在gc回收前會執行finalize()方法,只執行一次,並且是異步執行不保證執行成功,線程優先級低

代碼演示:

package com.wfd360.demo03GC.referDemo;

/**
 * @author 姿勢帝-博客園
 * @address https://www.cnblogs.com/newAndHui/
 * @WeChat 851298348
 * @create 06/20 8:34
 * @description
 */
public class FinalizeGC {
    public static FinalizeGC obj1 = null;

    /**
     * 重寫finalize方法
     * @throws Throwable
     */
    @Override
    protected void finalize() throws Throwable {
        super.finalize();
        System.out.println("執行finalize方法");
        // 自救,在回收時建立引用鏈
        FinalizeGC.obj1 = this;
    }

    public static void main(String[] args) throws InterruptedException {
        obj1  = new FinalizeGC();

        obj1 = null;
        System.gc();
        Thread.sleep(600);
        System.out.println("第一次自救成功:"+obj1);

        obj1 = null;
        System.gc();
        Thread.sleep(600);
        System.out.println("第二次自救失敗,不會再次執行finalize方法:"+obj1);
    }
}

View Code

測試結果:

 完美!

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※為什麼 USB CONNECTOR 是電子產業重要的元件?

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※台北網頁設計公司全省服務真心推薦

※想知道最厲害的網頁設計公司"嚨底家"!

新北清潔公司,居家、辦公、裝潢細清專業服務

※推薦評價好的iphone維修中心

西門子檢討澳洲煤礦案 瑞典環保少女籲做對的事

摘錄自2020年01月11日中央通訊社澳洲報導

德國西門子公司(Siemens AG)即將公布是否參與協助一項澳洲煤礦開採計畫,瑞典環保少女童貝里今天(11日)呼籲西門子做出正確的決定。

童貝里(Greta Thunberg)今天在推特(Twitter)發文:「星期一(13日),他們(西門子)將宣布決定。請幫助他們做出唯一正確的決定。」環保人士憂心,繼續使用煤炭會導致二氧化碳排放量增加,二氧化碳則是造成全球暖化的相關氣體。

西門子公司表示,他們將於13日前決定,是否參與印度阿達尼電力公司(Adani Power)興建的煤礦場計畫。

澳洲相當依賴燃煤電廠,是全球人均碳排放量最高的國家之一。澳洲政府去年批准阿達尼電力公司在昆士蘭州(Queensland)興建新的煤礦場,這座煤礦場預計每年生產800萬至1000萬噸燃料用煤。

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※為什麼 USB CONNECTOR 是電子產業重要的元件?

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※台北網頁設計公司全省服務真心推薦

※想知道最厲害的網頁設計公司"嚨底家"!

新北清潔公司,居家、辦公、裝潢細清專業服務

※推薦評價好的iphone維修中心

雷諾因制動器隱患在歐洲召回約8000輛Twizy電動車

雷諾日前宣佈在歐洲市場召回大約8,000輛Twizy,原因是上述車輛制動器存在問題。

雷諾表示,部分Twizy電動車的制動液存在緩慢洩露的情況,原因可能是部分該車型在工廠進行組裝時,制動液的密封部件受到損壞。

雷諾日前就此問題向歐洲地區大約8,000名Twizy電動車的車主進行了通報,並建議車主將車輛送回經銷商處進行維修。

今年3月份雷諾向法國市場推出了Twizy電動車,並隨後將該車型投放至歐洲其它國家,該車型的概念車曾在2009年法蘭克福車展中首次亮相。

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※為什麼 USB CONNECTOR 是電子產業重要的元件?

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※台北網頁設計公司全省服務真心推薦

※想知道最厲害的網頁設計公司"嚨底家"!

新北清潔公司,居家、辦公、裝潢細清專業服務

※推薦評價好的iphone維修中心

廣汽首款混合動力車型傳祺亮相廣州車展

在此次廣州車展上,廣汽發佈了該品牌首款型傳祺混動版。

新車的外觀與普通版車型基本保持一致,只是車頭和車尾的LOGO採用了藍色底色以表明這款車與普通版車型的不同,另外前進氣格柵加入了更多鍍鉻裝飾條。

該車的混合動力技術為廣汽自主研發,新車已經進入國家的公務車採購目錄,預計公車採購將成為它的主要銷售份額。動力方面,混動版傳祺在驅動方式上將有兩驅和四驅可選,對應的百公里綜合油耗分別為7.5L/km和6.6L/km。汽油機方面,它搭載的1.8L發動機最大功率可達106kW(144PS),電動機方面的資訊還尚不明確。

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※為什麼 USB CONNECTOR 是電子產業重要的元件?

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※台北網頁設計公司全省服務真心推薦

※想知道最厲害的網頁設計公司"嚨底家"!

新北清潔公司,居家、辦公、裝潢細清專業服務

※推薦評價好的iphone維修中心

福汽集團投資8000萬元開展A級純電動轎車研發專案

福汽集團與榕籍院士郭孔輝共同建立福汽集團汽車工程研究院院士工作站,開展“A級純電動轎車研發”項目合作。該專案總投資8000萬元,預計可實現產值9億元。目前,該專案已被列為福建省“百項千億”專案及省科技廳2013年“863”儲備專案。

工作站將以福汽集團汽車工程研究院為依託,充分發揮以郭孔輝院士領銜的專家們多學科、多專業的學術優勢和豐富的從業經驗,進行多層次、寬領域的合作,為福汽集團在產業政策的消化、利用以及企業發展戰略和發展規劃的研究提供諮詢和服務,並為福汽集團、發動機、微車產品等領域的自主研發、技術創新提供指導和幫助。

 “A級純電動轎車研發”項目合作將在量產化純電動轎車的底盤換電系統、資訊交互系統、動力系統等核心技術方面展開系統研發。專案立足於福汽集團的整車開發優勢,同時聯合了吉林大學、同濟大學、東南汽車、新鄉新能公司等單位,組建聯合專案團隊共同開發。

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※為什麼 USB CONNECTOR 是電子產業重要的元件?

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※台北網頁設計公司全省服務真心推薦

※想知道最厲害的網頁設計公司"嚨底家"!

新北清潔公司,居家、辦公、裝潢細清專業服務

※推薦評價好的iphone維修中心