「虹之松原」原來是海岸保安林 國寶級景點靠公私協力經營

環境資訊中心特約記者 廖靜蕙報導

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

【其他文章推薦】

※帶您來了解什麼是 USB CONNECTOR  ?

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※教你寫出一流的銷售文案?

2020國際觀鳥馬拉松 12/5開跑

由雲嘉南風景區管理處主辦的2020台灣國際觀鳥馬拉松大賽,有32支隊伍報名參加,其中國內隊伍有29隊,國際隊有3隊。雲網頁設計管處徐振能處長表示,競賽將於12月5日舉辦,今年有親子隊7隊,每隊可獲得精美獎品1份。而3支國際隊伍鳥如何寫文案友,分別來自南非、美國、加拿大、愛爾蘭等國。

徐振能處長表示,這項國際觀鳥馬拉松iphone維修大賽於2012年開始舉辦,是全台網頁設計唯一比賽範圍跨越雲林、嘉義、台南等3縣市,貨運賞鳥環境從濱海到山巔,鳥類涵蓋水鳥與山鳥。今年活動報名至10月31日截止,原訂國內隊報名隊伍數25隊,報名隊數卻有29隊,為滿足鳥友需求增加4隊。

徐振能處長表示,台北網頁設計為鼓勵親子組租車隊參加,凡包裝行銷參賽可獲得精美獎品1份,今年親子隊台北網頁設計有7隊,另外,報名者呈FB行銷現年輕化,有35%屬年輕網頁設計公司鳥友。歷年賽事至少有6國以上銷售文案賞鳥人士來台參加,受肺炎疫情影響,今年有3支國際隊伍,分別來自南非、美國、加拿大、愛爾蘭等國。

【Spring註解驅動開發】在@Import註解中使用ImportBeanDefinitionRegistrar向容器中註冊bean

寫在前面

在前面的文章中,我們學習了如何使用@Import註解向Spring容器中導入bean,可以使用@Import註解快速向容器中導入bean,小夥伴們可以參見《【Spring註解驅動開發】使用@Import註解給容器中快速導入一個組件》。可以在@Import註解中使用ImportSelector接口導入bean,小夥伴們可以參見《【Spring註解驅動開發】在@Import註解中使用ImportSelector接口導入bean》一文。今天,我們就來說說,如何在@Import註解中使用ImportBeanDefinitionRegistrar向容器中註冊bean。

項目工程源碼已經提交到GitHub:https://github.com/sunshinelyz/spring-annotation

ImportBeanDefinitionRegistrar概述

概述

我們先來看看ImportBeanDefinitionRegistrar是個什麼鬼,點擊進入ImportBeanDefinitionRegistrar源碼,如下所示。

package org.springframework.context.annotation;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.beans.factory.support.BeanNameGenerator;
import org.springframework.core.type.AnnotationMetadata;

public interface ImportBeanDefinitionRegistrar {

	default void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry,
			BeanNameGenerator importBeanNameGenerator) {

		registerBeanDefinitions(importingClassMetadata, registry);
	}

	default void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
	}

}

由源碼可以看出,ImportBeanDefinitionRegistrar本質上是一個接口。在ImportBeanDefinitionRegistrar接口中,有一個registerBeanDefinitions()方法,通過registerBeanDefinitions()方法,我們可以向Spring容器中註冊bean實例。

Spring官方在動態註冊bean時,大部分套路其實是使用ImportBeanDefinitionRegistrar接口。

所有實現了該接口的類都會被ConfigurationClassPostProcessor處理,ConfigurationClassPostProcessor實現了BeanFactoryPostProcessor接口,所以ImportBeanDefinitionRegistrar中動態註冊的bean是優先於依賴其的bean初始化的,也能被aop、validator等機制處理。

使用方法

ImportBeanDefinitionRegistrar需要配合@Configuration和@Import註解,@Configuration定義Java格式的Spring配置文件,@Import註解導入實現了ImportBeanDefinitionRegistrar接口的類。

ImportBeanDefinitionRegistrar實例

既然ImportBeanDefinitionRegistrar是一個接口,那我們就創建一個MyImportBeanDefinitionRegistrar類,實現ImportBeanDefinitionRegistrar接口,如下所示。

package io.mykit.spring.plugins.register.condition;

import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.type.AnnotationMetadata;

/**
 * @author binghe
 * @version 1.0.0
 * @description ImportBeanDefinitionRegistrar的實現類
 */
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {

    /**
     * AnnotationMetadata: 當前類的註解信息
     * BeanDefinitionRegistry:BeanDefinition註冊類
     * 通過調用BeanDefinitionRegistry接口的registerBeanDefinition()方法,可以將所有需要添加到容器中的bean注入到容器中。
     */
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry){

    }
}

可以看到,這裏,我們先創建了MyImportBeanDefinitionRegistrar類的大體框架。接下來,我們在PersonConfig2類上的@Import註解中,添加MyImportBeanDefinitionRegistrar類,如下所示。

@Configuration
@Import({Department.class, Employee.class, MyImportSelector.class, MyImportBeanDefinitionRegistrar.class})
public class PersonConfig2 {

接下來,創建一個Company類,作為測試測試ImportBeanDefinitionRegistrar接口的bean,如下所示。

package io.mykit.spring.plugins.register.bean;

/**
 * @author binghe
 * @version 1.0.0
 * @description 測試ImportBeanDefinitionRegistrar接口的使用
 */
public class Company {
}

接下來,就要實現MyImportBeanDefinitionRegistrar類中的registerBeanDefinitions()方法的邏輯了,添加邏輯后的registerBeanDefinitions()方法如下所示。

    /**
     * AnnotationMetadata: 當前類的註解信息
     * BeanDefinitionRegistry:BeanDefinition註冊類
     * 通過調用BeanDefinitionRegistry接口的registerBeanDefinition()方法,可以將所有需要添加到容器中的bean注入到容器中。
     */
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry){
        boolean employee = registry.containsBeanDefinition("employee");
        boolean department = registry.containsBeanDefinition("department");
        if (employee && department){
            BeanDefinition beanDefinition = new RootBeanDefinition(Company.class);
            registry.registerBeanDefinition("company", beanDefinition);
        }
    }

registerBeanDefinitions()方法的實現邏輯很簡單,就是判斷Spring容器中是否同時存在以employee命名的bean和以department命名的bean,如果同時存在以employee命名的bean和以department命名的bean,則向Spring容器中注入一個以company命名的bean。

接下來,我們就運行SpringBeanTest類中的testAnnotationConfig7()方法來進行測試,輸出結果信息如下所示。

org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
personConfig2
io.mykit.spring.plugins.register.bean.Department
io.mykit.spring.plugins.register.bean.Employee
io.mykit.spring.plugins.register.bean.User
io.mykit.spring.plugins.register.bean.Role
person
binghe001

可以看到,在輸出結果中,並沒有看到“company”,這是因為輸出結果中存在io.mykit.spring.plugins.register.bean.Department和io.mykit.spring.plugins.register.bean.Employee,並不存在我們代碼邏輯中的department和employee。所以,我們將registerBeanDefinitions()方法的邏輯稍微修改下,修改后的代碼如下所示。

/**
  * AnnotationMetadata: 當前類的註解信息
  * BeanDefinitionRegistry:BeanDefinition註冊類
  * 通過調用BeanDefinitionRegistry接口的registerBeanDefinition()方法,可以將所有需要添加到容器中的bean注入到容器中。
  */
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry){
    boolean employee = registry.containsBeanDefinition(Employee.class.getName());
    boolean department = registry.containsBeanDefinition(Department.class.getName());
    if (employee && department){
        BeanDefinition beanDefinition = new RootBeanDefinition(Company.class);
        registry.registerBeanDefinition("company", beanDefinition);
    }
}

接下來,我們再次運行SpringBeanTest類中的testAnnotationConfig7()方法來進行測試,輸出結果信息如下所示。

org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
personConfig2
io.mykit.spring.plugins.register.bean.Department
io.mykit.spring.plugins.register.bean.Employee
io.mykit.spring.plugins.register.bean.User
io.mykit.spring.plugins.register.bean.Role
person
binghe001
company

可以看到,此時輸出了company,說明Spring容器中已經成功註冊了以company命名的bean。

好了,咱們今天就聊到這兒吧!別忘了給個在看和轉發,讓更多的人看到,一起學習一起進步!!

項目工程源碼已經提交到GitHub:https://github.com/sunshinelyz/spring-annotation

寫在最後

如果覺得文章對你有點幫助,請微信搜索並關注「 冰河技術 」微信公眾號,跟冰河學習Spring註解驅動開發。公眾號回復“spring註解”關鍵字,領取Spring註解驅動開發核心知識圖,讓Spring註解驅動開發不再迷茫。

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

【其他文章推薦】

※帶您來了解什麼是 USB CONNECTOR  ?

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※教你寫出一流的銷售文案?

特斯拉將調整全球超級充電站充電價格,車主錯愕

根據國外專門報導電動車產業消息的《Electrek》網站報導,電動車大廠特斯拉(Tesla)正式終止任何形式的免費充電計畫之後,準備將全球超級充電站(Supercharger)充電價格平均提高 33%,這舉動令車主錯愕。

自 2018 年 11 月以來,特斯拉所有新款電動車都必須遵守新超級充電站充電付費計畫,雖然沒有擴及 2018 年 11 月前購買特斯拉電動車的車主,特斯拉仍舊對這些車主提供有限度的免費充電服務。不過,這項優惠措施到 2019 年 1 月底為止,也就是之後再也不會有任何特斯拉車主有免費充電服務;新付費方式將以每度(小時千瓦;1kWh),或是部分地區每分鐘來計算充電費用。

觀察特斯拉的新充電費率,將以不同地區、甚至每個充電站的使用需求計價。特斯拉還希望根據當地電價,訂定更合理、更全面的價格。換句話說,這會造成大多數地區的超級充電樁價格大幅上漲。

在 2018 年,特斯拉已提高美國超級充電站的充電價格。調漲後多數地區的充電價格漲幅為 20%~40%,部分地區漲幅甚至高達 100%。以紐約市為例,過去是每度 0.24 美元,現在則是 0.32 美元,上漲 33%。加州地區,過去每度為 0.26 美元,調整之後是 0.32 到 0.36 美元不等。這次特斯拉全球充電價格調漲,美國市場已是第 2 次漲價。

歐洲方面,雖然大多數市場充電價格仍維持每度 0.28~0.32 歐元,以特斯拉在歐洲最重要的市場和超級充電站最密集的挪威來說,充電價格預計從每小時千瓦 1.4 挪威克朗,上升到 1.86 挪威克朗,幾乎漲了 33%。相信未來其他地區也會是類似漲幅。

特斯拉一直聲稱超級充電站「永遠不會成為利潤中心」。漲價計畫決定後,面對記者的詢問,特斯拉還是重申這點,並表示正在調整超級充電站的充電價格,希望更能反映當地電力成本,以及場地使用情況的差異。隨著特斯拉電動車增多,未來也繼續每週開設新超級充電站,讓更多消費者可長途行駛,並享受到比汽油價格低的充電價格,達到零排碳量的目標。未來,還希望利用超級充電站獲得的收入,建立更多充電站。

目前特斯拉全世界共有 1,422 個超級充電站,共有 12,011 個充電樁,而特斯拉的目標,是在 2019 年將這個數字倍增。

(合作媒體:。首圖來源: CC BY 2.0)

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

【其他文章推薦】

※帶您來了解什麼是 USB CONNECTOR  ?

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※教你寫出一流的銷售文案?

用高科技提升訓練效率 竹市消防首創「MR實境」救災場景

新竹市消防教育訓練基地獲經濟部前瞻計畫補助,導入全國首創MR(混合實境)、VR(虛擬實境)等,模擬出幾乎真實場景,還有高溫濃煙、火焰閃燃等,都是過去消防員如何寫文案唯有透過實際救災才能接觸火災危險,全面提升消防員救災訓練效率。竹市長林智銷售文案堅今搶先體驗,他與消防員組隊,在MR(混合實境)撲滅失火民宅,並救出生還者。

林智堅市長9日到訓練基地視察,首度體驗MR(混合實境)救災訓練設施,透過實境眼鏡,能讓受訓者眼中的訓練基地變成失火民宅實況,起火、受困民眾皆栩栩如生。林智堅市長擔任水線瞄子手(瞄子即為消防水帶前網頁設計端噴射頭),在消防訓練教官指導與隊員協助下,嘗試滅火更救出生還者。他也體驗消防員訓練日常,先換裝網頁設計公司消防衣,負重爬兩層樓梯,還接受搜救訓練,進入倒塌大樓內,協助搜尋生還者。

林智堅市長說,MR(混合實境)系統,最佳優點消防訓練教官可透過系統看見學員視野,提iphone維修醒學員忽略的救災盲點,即時糾正並指導救災,救災訓練更加全面。另外,該系統也可讓學員重複練習,不須像過去顧慮模擬真實場景的高成本。讓消防員能透過高科技身歷其境火場實況,事半功倍做好救災應變準備。

MR能高度擬真模擬救災現場狀貨運況,帶上實境眼鏡能看見火場,MR的「感應握把」更可裝在連接水帶的噴頭(即瞄子)上,學員戴上眼鏡、手持握把,FB行銷不只身歷其境,連器材的觸感及重量都十分逼真。透過VR(虛擬實境)打造的消包裝行銷防救災模擬演練系統,還網頁設計特別針對新竹街景特色,模擬出大型購物中心(仿大遠百)、高層建租車築物(仿國賓飯店)、狹小巷弄地區(仿關帝廟)等火災樣貌,以便消防指揮官訓練調度指揮。

消防局長李世恭表示,新竹市消防教育訓練基地成立迄今,已有16年,代訓人數已超過3萬4000人。利用中央補助經費建立「多功能應用台北網頁設計救助訓練設施」仿造山坡、密閉空間場景,更可全面訓練學員救災能力。未來,新竹市消防教育訓練基地不僅訓練消防員,也將轉台北網頁設計化訓練課程,協助國內大型企業及高科技公司等單位,訓練公安人員,提升自我防護能力,共創防救災產、官、學界三贏。

Java 從入門到進階之路(二十三)

在之前的文章我們介紹了一下 Java 中的  集合框架中的Collection 的迭代器 Iterator,本章我們來看一下 Java 集合框架中的Collection 的泛型。

在講泛型之前我們先來看下面一段代碼:

 1 public class Main {
 2     public static void main(String[] args) {
 3         Point point = new Point(1, 2);
 4 
 5         point.setX(2);
 6         int ix = point.getX();
 7         System.out.println(ix); // (2, 2)
 8 
 9         /**
10          * 如果想要 x 值變為 double 類型則可以強轉為 double 類型
11          * */
12         point.setX(2);
13         double dx = (double) point.getX();
14         System.out.println(dx); // 2.0
15     }
16 }
17 
18 class Point {
19     private int x;
20     private int y;
21 
22     public Point(int x, int y) {
23         this.x = x;
24         this.y = y;
25     }
26 
27     public int getX() {
28         return x;
29     }
30 
31     public void setX(int x) {
32         this.x = x;
33     }
34 
35     public int getY() {
36         return y;
37     }
38 
39     public void setY(int y) {
40         this.y = y;
41     }
42 
43     @Override
44     public String toString() {
45         return "(" + x + ", " + y + ")";
46     }
47 }

上面的代碼我們之前的文章講過,我們可以通過傳入 x 和 y 值來定義 Point 點,如果我們想要 double 類型的點時需要造型為 double 類型,那我要定義漢字類型的呢?那就造型成 String 類型,這就很麻煩,每次都需要自己來造型,有種鞋不合腳的感覺,那能不能定義我想要什麼類型就是什麼類型呢,如下:

 1 public class Main {
 2     public static void main(String[] args) {
 3         Point<Integer> point1 = new Point<Integer>(1, 2); // 必須是包裝類
 4         point1.setX(1);
 5         System.out.println(point1.getX()); // 1
 6 
 7         Point<Double> point2 = new Point<Double>(1.1, 2.1); // 必須是包裝類
 8         point2.setX(1.2);
 9         System.out.println(point2.getX()); // 1.2
10 
11         Point<String> point3 = new Point<String>("一", "二"); // 必須是包裝類
12         point3.setX("三");
13         System.out.println(point3.getX()); //
14     }
15 }
16 
17 /**
18  * 泛型
19  * 又稱參數化類型,是將當前類的屬性的類型,方法參數的類型及方法
20  * 返回值的類型的定義權移交給使用者,
21  * 使用者在創建當前類的同時將泛型的試劑類型傳入
22  * 数字和字母組合,数字不能開頭
23  */
24 class Point<T> { // 定義為泛型 T 類型
25     private T x;
26     private T y;
27 
28     public Point(T x, T y) {
29         this.x = x;
30         this.y = y;
31     }
32 
33     public T getX() {
34         return x;
35     }
36 
37     public void setX(T x) {
38         this.x = x;
39     }
40 
41     public T getY() {
42         return y;
43     }
44 
45     public void setY(T y) {
46         this.y = y;
47     }
48 
49     @Override
50     public String toString() {
51         return "(" + x + ", " + y + ")";
52     }
53 }

從上面的代碼中,我們定義了一個 T 的類型 Point,當我們要實例化該類時,根據自己的需求傳入想要的包裝類類型即可,這樣就滿足了不同的需求,各取所需。 

泛型從底層來說其實就是 Object,定義了泛型只是編譯器在做一些驗證工作,當我們對泛型類型設置值時,會檢查是否滿足類型要求,當我們獲取一個泛型類型的值時,會自動進行類型轉換。

在平時我們是很少自己來定義泛型的,泛型是用來約束集合中元素的類型,如下:

 1 import java.util.ArrayList;
 2 import java.util.Collection;
 3 import java.util.Iterator;
 4 
 5 public class Main {
 6     public static void main(String[] args) {
 7         Collection<String> collection = new ArrayList<String>(); // 只能添加 String 類型的元素
 8         collection.add("one");
 9         collection.add("two");
10         collection.add("thee");
11         collection.add("four");
12         // collection.add(1); // 編譯錯誤
13         for (String string : collection) {
14             System.out.println(string); // one two three four
15         }
16         Iterator<String> iterator = collection.iterator();
17         while (iterator.hasNext()) {
18             // String string = (String) iterator.next(); 不需要再造型
19             String string = iterator.next();
20             System.out.println(string); // one two three four
21         }
22     }
23 }

  

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

【其他文章推薦】

※帶您來了解什麼是 USB CONNECTOR  ?

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※教你寫出一流的銷售文案?

防海水高溫傷核反應爐 瑞典要求核電廠提計畫

摘錄自2018年8月21日中央社報導

瑞典核能監管機關瑞典輻射安全局局長培爾松20日表示,為防範海水高溫傷害核反應爐,他們已要求國內核電廠營運商近月內提出因應計畫。

今夏熱浪造成瑞典7月氣溫攀升至歷史新高,用來冷卻核反應爐的海水溫度也因此遠高於正常水準,並超過安全標準,導致瑞典數個核電廠反應爐必須關閉或減少發電量。

上回瑞典輻射安全局(Swedish Radiation Safety Authority, SSM)要求核電廠提出反應爐修改計畫,是在2011年日本發生福島核災之後。當時提出截至2020年的修改計畫,所需經費達數億歐元。

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

【其他文章推薦】

※帶您來了解什麼是 USB CONNECTOR  ?

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※教你寫出一流的銷售文案?

通用汽車關廠效應!白宮:將取消電動車、再生能源補貼

通用汽車(General Motors Co.,GM)上週決定關閉美國工廠、裁減員工,並把焦點轉向電動車,引發美國總統川普(Donald Turmp)怒火,也堅定了川普政府終結電動車、再生能源補貼的決心。白宮國家經濟委員會會長庫卓(Larry Kudlow)透露,歐巴馬時期的補貼政策將在 2020 年或 2021 年全面終止。

路透社、The Hill、Mashable 等外電報導,庫卓 3 日在被問到 GM 關廠裁員的行動時,提到美國消費者購買插電式電動車時、都可獲得 2,500~7,500 美元的稅收抵免優惠,當中也包括 GM 製造的車種。

庫卓說,白宮希望終結電動車及其他歐巴馬執政時推出的補貼政策,當中也會包括可再生能源,預計終止的時間大概會落於 2020 年或 2021 年。

根據國會規定,每家製造商只能為 20 萬輛汽車提供稅收抵免優惠,在超過上限後,補貼就會逐步減少。GM 預測該公司 2018 年底就會達到門檻,依據當前聯邦法令的規定,這代表 GM 的汽車抵稅優惠方案將在 2020 年告終。

特斯拉今年 7 月就已宣布抵達 20 萬輛汽車的門檻。其他汽車製造商則還要花上幾年才會觸及。

川普上週威脅要剔除 GM 申請電動車抵稅優惠補貼的資格,以報復該公司關廠裁員的決定。不過,專家直指,白宮無法單方面修改電動車抵稅優惠的法令。

聯合國(UN)最近才剛發布評估報告,直指氣候變遷恐對環境帶來嚴重危害,呼籲政府直接介入、避免災難爆發。不過,白宮認為此份報告太過誇張。美國甫於 7 月退出巴黎協議。

…..and G.M. would not be closing their plants in Ohio, Michigan & Maryland. Get smart Congress. Also, the countries that send us cars have taken advantage of the U.S. for decades. The President has great power on this issue – Because of the G.M. event, it is being studied now!

— Donald J. Trump (@realDonaldTrump)

(本文內容由 授權使用。首圖來源:)

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

【其他文章推薦】

※帶您來了解什麼是 USB CONNECTOR  ?

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※教你寫出一流的銷售文案?

Enevate推出電動車5分鐘極速快充電池技術

  鋰離子(Li-ion)電池技術公司Enevate Corporation宣布為電動車(EV)推出HD-Energy技術,僅僅5分鐘高能量密度的極速快充可將行駛里程增加多達390公里,充電60秒行駛里程可增加最多達80公里。這一快速充電技術所帶來的極短的充電時間優於目前所有其他鋰離子電池技術,同時滿足汽車對能量密度、里程和成本的進一步要求。Enevate計劃將其以矽為主材的HD-Energy技術授權給全球的電池和電動車製造商及供應商。   這一創新的極速快充技術打破了電動車普及的重重壁壘。一直以來,由於有限的行駛里程所導致的駕駛「里程焦慮」、充電時間過長以及高成本等原因,電動車始終難以普及。如今, Enevate應用於鎳鈷錳(NCM)電動車電池的突破性矽鋰離子電池技術經測試已可用高達10C的充電速率在5分鐘內充電至75%的電池容量且不會影響到電池的使用壽命。同時,其超過750Wh/L的能量密度不會在行駛里程上打折扣。而傳統石墨電池在極速快充中會出現電池急劇退化的問題。   該5分鐘充電技術讓流通出入型充電站的應用成為可能,電動車駕駛人僅需等待幾分鐘即可完成「充電」,就像出入普通加油站一樣。此外,由於充電時間極短,一些電動車中可以選擇使用更小型的電池,使電動車更加多樣化並且經濟適用。   公司創始人兼首席技術官Benjamin Park博士表示:「Enevate以矽為主材的HD-Energy技術具備的優勢可實現新一代功能,將電動車推向全新水平。該技術支持極速快充,可在很短時間便捷地進行充電,具備有助於延長駕駛里程的更高能量密度,同時具備低溫操作的固有安全優勢,這些使其成為電動車電池的理想之選。」   Enevate的HD-Energy電池技術可在低至零下40°C的溫度下實現安全充放電,並且可在再生煞車期間捕獲更多的能量,從而延長了在寒冷氣候中的行駛里程。Enevate HD-Energy技術具備一個關鍵的內在安全優勢,即在快速充電和在低溫充電時可防止鋰析出,這是傳統石墨鋰離子電池所面臨的一個主要挑戰。   德克薩斯大學奧斯汀分校的鋰離子電池先驅John Goodenough博士對此表示贊同,他說:「Enevate以矽為主材的薄膜陽極和電池是一種極具創新性的方法,在電動車應用中具有很大的實用價值,可有效解決電動車普及所面臨的主要障礙。」   (資訊來源:Enevate;首圖來源:Enevate)

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

【其他文章推薦】

※帶您來了解什麼是 USB CONNECTOR  ?

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※教你寫出一流的銷售文案?

聚甘新

Java容器相關知識點整理

結合一些文章閱讀源碼后整理的Java容器常見知識點。對於一些代碼細節,本文不展開來講,有興趣可以自行閱讀參考文獻。

1. 思維導圖

各個容器的知識點比較分散,沒有在思維導圖上體現,因此看上去右半部分很像類的繼承關係。

2. 容器對比

類名 底層實現 特徵 線程安全性 默認迭代器實現(Itr)
ArrayList Object數組 查詢快,增刪慢 不安全,有modCount 數組下標
LinkedList 雙向鏈表 查詢慢,增刪快 不安全,有modCount 當前遍歷的節點
Vector Object數組 查詢快,增刪慢 方法使用synchronized確保安全(注1);有modCount 數組下標
Stack Vector 同Vector 同Vector 同Vector
HashSet HashMap (使用帶特殊參數的構造方法則為LinkedHashMap) 和HashMap一致 和HashMap一致 和HashMap一致
LinkedHashSet LinkedHashMap 和LinkedHashMap一致 和LinkedHashMap一致 和LinkedHashMap一致
TreeSet TreeMap 和TreeMap一致 和TreeMap一致 和TreeMap一致
TreeMap 紅黑樹和Comparator(注2) key和value可以為null(注2),key必須實現Comparable接口 非線程安全,有modCount 當前節點在中序遍歷的後繼
HashMap 見第3節 key和value可以為null 非線程安全,有modCount HashIterator按數組索引遍歷,在此基礎上按Node遍歷
LinkedHashMap extends HahsMap (注3), Node有前驅和後繼 可以按照插入順序或訪問順序遍歷(注4) 非線程安全,有modCount 同HshMap
ConcurrentHashMap 見第3節 key和value不能為null 線程安全(注1) 基於Traverser(注5)
Hashtable Entry數組 + Object.hashCode() + 同key的Entry形成鏈表 key和value不允許為null 線程安全, 有modCount 枚舉類或通過KeySet/EntrySet

操作的時間複雜度

  • ArrayList下標查找O(1),插入O(n)
  • 涉及到樹,查找和插入都可以看做log(n)
  • 鏈表查找O(n),插入O(1)
  • Hash直接查找hash值為 O(1)

注1:關於容器的線程安全

複合操作

無論是Vetcor還是SynchronizedCollection甚至是ConcurrentHashMap,複合操作都不是線程安全的。如下面的代碼[1]在併發環境中可能會不符合預期:

if (!vector.contains(element)) 
    vector.add(element); 
    ...
}
ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap();
map.put("key", 1);

// 多線程環境下執行
Integer currentVal = map.get("key");
map.put("key", currentVal + 1);

在複合操作的場景下,通用解法是對容器加鎖,但這樣會大幅降低性能。根據具體的場景來解決效果更好,如第二段代碼的場景,可以改寫為[1]

ConcurrentHashMap<String, AtomicInteger> map = new ConcurrentHashMap();
// 多線程環境下執行
map.get("key").incrementAndGet();

modCount和迭代器Iterator問題

modCount是大多數容器(比如ConcurrentHashMap就沒有)用來檢測是否發生了併發操作,從而判斷是否需要拋出異常通知程序員去處理的一個簡單的變量,也被稱為fast-fail。
一開始我注意到,Vector也有modCount這個屬性,這個字段用來檢測對於容器的操作期間是否併發地進行了其他操作,如果有會拋出併發異常。既然Vector是線程安全的,為什麼還會有modCount?順藤摸瓜,我發現雖然Vector的Iterator()方法是synchronized的,但是迭代器本身的方法並不是synchronized的。這就意味着在使用迭代器操作時,對Vector的增刪等操作可能導致併發異常。
為了避免這個問題,應該在使用Iterator時對Vector加鎖。
同理可以推廣到Collecitons.synchronizedCollection()方法,可以看到這個方法創建的容器,對於迭代器和stream方法,都有一行// Must be manually synched by user!的註釋。

注2:TreeMap的comparator和key

comparator是可以為空的,此時使用key的compare接口比較。因此,這種情況下如果key==null會拋NPE。

注3:

JDK8的HashMap中有afterNodeAccess()、afterNodeInsertion()、afterNodeRemoval()三個空方法,在LinkedHashMap中覆蓋,用於回調。

注4:LinkedHashMap插入順序和訪問順序

插入順序不必解釋。訪問順序指的是,每次訪問一個節點,都將它插入到雙向鏈表的末尾。

注5:Traverser

其實現類EntryIterator的構造方法實際上是有bug的[5]:它與子類的參數表順序不一致。
它能確保在擴容期間,每個節點只訪問一次。這個原理比較複雜,我沒有深入去看,可以參考本小節的參考文獻。

3. Hashtable & HashMap & ConcurrentHashMap

這是一個老生常談的話題了,但是涉及面比較廣,本節好好總結一下。
本節不列出具體的源碼,大部分直接給出結論,源碼部分分析可以參考文獻[7][8]。
table表示Map的hash值桶,即每一個元素對應所有同一個hash值的key-value對。

相同點

  • keySet、values、entrySet()首次使用時初始化

差異點

容器類型 底層實現(見說明4) key的hash方法 table下標計算 擴容后table容量(見說明1、5) 插入 clone hash桶的最大容量
Hashtable hash值桶數組 + 鏈表 hashCode() (hashCode & MAX_INT) % table.length origin*2+1 頭部插入 淺拷貝 MAXINT- 8
HashMap(1.7) hash值桶數組 + 鏈表 String使用sun.misc.Hashing.stringHash32,其他用hashCode()后多次異或摺疊(見說明2) (length-1) & hashCode origin*2 頭部插入(見說明6) 淺拷貝 2^30
HashMap(1.8) hash值桶數組 + 鏈表/紅黑樹(見說明3) hashCode()高低16位異或 (length-1) & hashCode origin*2(見說明7) 尾部插入 淺拷貝 2^30
ConcurrentHashMap(1.7) hash值桶數組 + Segment extends ReentrantLock(見說明9) + 數組 String使用sun.misc.Hashing.stringHash32,其他用hashCode()后多次異或摺疊和加法操作(見說明8) (length-1) & hashCode origin*2 頭部插入 不支持 2^30
ConcurrentHashMap(1.8) hash值桶數組 + 鏈表/紅黑樹(見說明10) hashCode()高低16位異或 % MAX_INT (length-1) & hashCode origin*2 尾部插入 不支持 2^30

說明

  1. HashMap和ConcurrentHashMap的key桶大小都是2的冪,便於將計算下標的取模操作轉化為按位與操作
  2. Map的key建議使用不可變類如String、Integer等包裝類型,其值是final的,這樣可以防止key的hash發生變化
  3. 1.8以後,鏈錶轉紅黑樹的閾值為8,紅黑樹轉回鏈表的閾值位6。8是鏈表和紅黑樹平均查找時間(n/2和logn)的閾值,不在7轉回是為了防止反覆轉換。
  4. 1.7的HashMap的Entry和1.8中的Node幾乎是一樣的,區別在於:後者的equals()使用了Objects.equals()做了封裝,而不是對象本身的equals()。另外鏈表節點Node和紅黑樹節點TreeNode沒有關係,後者是extends LinkedHashMap的Node,通過紅黑樹查找算法找value。1.7的ConcurrentHashMap的Node中value、next是用volatile修飾的。但是,1.8的ConcurrentHashMap有TreeNode<K,V> extends Node<K,V>,遍歷查找值時是用Node的next進行的。
  5. 擴容的依據是k-v容量>=擴容閾值threshold,而threshold= table數組大小 * 裝載因子。擴容前後hash值沒有變,但是取模(^length)變了,所以在新的table中所在桶的下標可能會變
  6. HashMap1.7的頭插法在併發場景下reszie()容易導致鏈表循環,具體的執行場景見文獻[7][9]。這一步不太好理解,我個人是用[9]的示意圖自己完整在紙上推演了一遍才理解。關鍵點在於,被中斷的線程,對同一個節點遍歷了兩次。雖然1.8改用了尾插法,仍然有循環引用的可能[10][11]
  7. 1.8的HashMap在resize()時,要將節點分開,根據擴容后多計算hash的那一位是0還是1來決定放在原來的桶[i]還是桶[i+原始length]中。
  8. 1.7中計算出hash值后,還會使用它計算所在的Segement
  9. put(key,value)時鎖定分段鎖,先用非阻塞tryLock()自旋,超過次數上限后升級為阻塞Lock()。
  10. 1.8的ConcurrentHashMap拋棄了Segement,使用synchronized+CAS(使用tabAt()計算所在桶的下標,實際是用UNSAFE類計算內存偏移量)[12]進行寫入。具體來說,當桶[i]為空時,CAS寫值;非空則對桶[i]加鎖[13]

ConcurrentHashMap的死鎖問題

1.7場景

對於跨段操作,如size()、containsValue(),是需要按Segement的下標遞增逐段加鎖、統計,然後按原先順序解鎖的。這樣就有一個很嚴重的隱患:如果線程A在跨段操作時,中間的Segement[i]被
線程B鎖定,B又要去鎖定Segement[j] (i>j),此時就發生了死鎖。

1.8場景

由於沒有段,也就沒有了跨段。但是size()還是要統計各個桶的數目,仍然有跨桶的可能。如何計算?如果沒有衝突發生,只將 size 的變化寫入 baseCount。一旦發生衝突,就用一個數組(counterCells)來存儲後續所有 size 的變化[14]
而containsValue()則藉助了Traverser(見第2節注5及參考文獻[15]),但是返回值不是最新的

參考文獻

沒有在文中特殊標註的文章,是參考了其結構或部分內容,進行了重新組織。

  1. Vector 是線程安全的?
  2. 使用ConcurrentHashMap一定線程安全?
  3. TreeMap原理實現及常用方法
  4. Java容器常見面試題
  5. Java高級程序員必備ConcurrentHashMap實現原理:擴容遍歷與計數
  6. Java容器面試總結
  7. Java:手把手帶你源碼分析 HashMap 1.7
  8. Java源碼分析:關於 HashMap 1.8 的重大更新 注:本篇的resize()源碼和我本地JDK8的不一致!
  9. HashMap底層詳解-003-resize、併發下的安全問題
  10. JDK8中HashMap依然會死循環!
  11. HashMap在jdk1.8中也會死循環
  12. ConcurrentHashMap中tabAt方法分析
  13. HashMap?ConcurrentHashMap?相信看完這篇沒人能難住你!
  14. ConcurrentHashMap 1.8 計算 size 的方式
  15. Java集合類框架學習 5.3—— ConcurrentHashMap(JDK1.8)

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

【其他文章推薦】

※帶您來了解什麼是 USB CONNECTOR  ?

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※教你寫出一流的銷售文案?

聚甘新