分類
發燒車訊

jvm入門及理解(六)——垃圾回收與算法

一、jvm垃圾回收要做的事情

  • 哪些內存需要回收
  • 什麼時候回收
  • 怎麼回收

二、如何判斷對象已經死亡,或者說確定為垃圾

  1. 引用計數法:

    給對象中添加一個引用計數器,每當有一個地方引用它時,計數器的值就加1;當引用失效時,計數器值就減1;任何時刻計數器為0的對象就是不可能再被使用的。這也就是需要回收的對象,簡單地說,即一個對象如果沒有任何與之關聯的引用,即他們的引用計數都為 0,則說明對象不太可能再被用到,那麼這個對象就是可回收的對象。

    引用計數法是對象記錄自己被多少程序引用,引用計數為零的對象將被清除。

    計數器表示的是有多少程序引用了這個對象(被引用數)。計數器是無符號的整數。

  2. 根搜索算法:

    通過一系列成為GC roots的點作為起點,向下搜索,當一個對象到任何GC Roots時沒有引用鏈相連,則說明對象已經死亡。

    如果在GC roots和一個對象之間沒有可達路徑(引用鏈),則稱該對象是不可達的。要注意的是,不可達對象不等價於可回收對象,不可達對象變為可回收對象至少要經過兩次標記 過程。兩次標記后仍然是可回收對象,則將面臨回收。

    jvm會將以下的對象定義為GC Roots:

 

  • Java虛擬機棧中引用的對象:比如方法裏面定義這種局部變量 User user= new User();
  • 方法區中的靜態屬性引用的對象:比如 private static User user = new User();
  • 常量引用的對象:比如 private static final  User user = new User();
  • 本地方法棧(JNI)中引用的對象

三、垃圾回收算法

  1. 標記清除算法(Mark-Sweep)

    是最基礎的垃圾回收算法,分為兩個階段,標註和清除。標記階段標記出所有需要回收的對象,清除階段回收被標記的對象所佔用的空間。首先從根開始將可能被引用的對象用遞歸的方式進行標記,然後將沒有標記到的對象作為垃圾進行回收。

 

 

從圖中我們就可以發現,該算法最大的問題是內存碎片化嚴重,後續可能發生大對象不能找到可利用空間的問題。

 

 

  2. 複製算法(copying)

   為了解決 Mark-Sweep 算法內存碎片化的缺陷而被提出的算法。按內存容量將內存劃分為等大小 的兩塊。每次只使用其中一塊,當這一塊內存滿后將尚存活的對象複製到另一塊上去,把已使用 的內存清掉,如圖:

 

 

 

 

 

 這種算法雖然實現簡單,內存效率高,不易產生碎片,但是最大的問題是可用內存被壓縮到了原 本的一半。且存活對象增多的話,Copying 算法的效率會大大降低。

  

  3.標記整理算法(Mark-Compact)

   結合了以上兩個算法,為了避免缺陷而提出。標記階段和 Mark-Sweep 算法相同,標記后不是清 理對象,而是將存活對象移向內存的一端。然後清除端邊界外的對象。如圖:

 

 

 

四、分代收集算法

  介紹:分代收集法是目前大部分 JVM 所採用的方法,其核心思想是根據對象存活的不同生命周期將內存 劃分為不同的域,一般情況下將 GC 堆劃分為老生代(Tenured/Old Generation)和新生代(Young Generation)。老生代的特點是每次垃圾回收時只有少量對象需要被回收,新生代的特點是每次垃圾回收時都有大量垃圾需要被回收,因此可以根據不同區域選擇不同的算法。

  1. 新生代與複製算法

    目前大部分 JVM 的 GC 對於新生代都採取 Copying 算法,因為新生代中每次垃圾回收都要 回收大部分對象,即要複製的操作比較少,但通常並不是按照 1:1 來劃分新生代。一般將新生代 劃分為一塊較大的 Eden 空間和兩個較小的 Surviror 空間(From Space, To Space),每次使用 Eden 空間和其中的一塊 Survivor 空間,當進行回收時,將該兩塊空間中還存活的對象複製到另 一塊 Survivor 空間中。

  

 

 

 假設from space為s0,to space 為s1

算法過程:

  1. Eden+S0可分配新生對象;
  2. 對Eden+S0進行垃圾收集,存活對象複製到S1清理Eden+S0。一次新生代GC結束。
  3. Eden+S1可分配新生對象;
  4. 對Eden+S1進行垃圾收集,存活對象複製到S0清理Eden+S1。二次新生代GC結束。
  5. 循環1。

  2.老年代與標記整理算法

老年代因為每次只回收少量對象,因而採用 Mark-Compact 算法。

1. JAVA 虛擬機提到過的處於方法區的永生代(Permanet Generation),它用來存儲 class 類, 常量,方法描述等。對永生代的回收主要包括廢棄常量和無用的類。

2. 對象的內存分配主要在新生代的 Eden Space 和 Survivor Space 的 From Space(Survivor 目 前存放對象的那一塊),少數情況會直接分配到老生代。

3. 當新生代的 Eden Space 和 From Space 空間不足時就會發生一次 GC,進行 GC 后,Eden Space 和 From Space 區的存活對象會被挪到 To Space,然後將 Eden Space 和 From Space 進行清理。

4. 如果 To Space 無法足夠存儲某個對象,則將這個對象存儲到老生代。

5. 在進行 GC 后,使用的便是 Eden Space 和 To Space 了,如此反覆循環。

6. 當對象在 Survivor 區躲過一次 GC 后,其年齡就會+1。默認情況下年齡到達 15 的對象會被 移到老生代中。

 

五、分區收集算法

分區算法則將整個堆空間劃分為連續的不同小區間, 每個小區間獨立使用, 獨立回收. 這樣做的 好處是可以控制一次回收多少個小區間 , 根據目標停頓時間, 每次合理地回收若干個小區間(而不是 整個堆), 從而減少一次 GC 所產生的停頓。

 

六、java中的四種引用

  • 強引用

在 Java 中最常見的就是強引用,把一個對象賦給一個引用變量,這個引用變量就是一個強引 用。當一個對象被強引用變量引用時,它處於可達狀態,它是不可能被垃圾回收機制回收的,即 使該對象以後永遠都不會被用到 JVM 也不會回收。因此強引用是造成 Java 內存泄漏的主要原因之一,直接new的對象就是強引用的。

  • 軟引用

軟引用需要用 SoftReference 類來實現,對於只有軟引用的對象來說,當系統內存足夠時它 不會被回收,當系統內存空間不足時它會被回收。軟引用通常用在對內存敏感的程序中。

  • 弱引用

弱引用需要用 WeakReference 類來實現,它比軟引用的生存期更短,對於只有弱引用的對象 來說,只要垃圾回收機制一運行,不管 JVM 的內存空間是否足夠,總會回收該對象佔用的內存。

  • 虛引用

虛引用需要 PhantomReference 類來實現,它不能單獨使用,必須和引用隊列聯合使用。虛 引用的主要作用是跟蹤對象被垃圾回收的狀態。

 

七、GC 垃圾收集器

Java 堆內存被劃分為新生代和年老代兩部分,新生代主要使用複製和標記-清除垃圾回收算法; 年老代主要使用標記-整理垃圾回收算法,因此 java 虛擬中針對新生代和年老代分別提供了多種不 同的垃圾收集器,JDK1.6 中 Sun HotSpot 虛擬機的垃圾收集器如下:

 

新生代:

  1.  Serial 垃圾收集器(單線程、複製算法)

Serial(英文連續)是最基本垃圾收集器,使用複製算法,曾經是JDK1.3.1 之前新生代唯一的垃圾 收集器。Serial 是一個單線程的收集器,它不但只會使用一個 CPU 或一條線程去完成垃圾收集工 作,並且在進行垃圾收集的同時,必須暫停其他所有的工作線程,直到垃圾收集結束。 Serial 垃圾收集器雖然在收集垃圾過程中需要暫停所有其他的工作線程,但是它簡單高效,對於限 定單個 CPU 環境來說,沒有線程交互的開銷,可以獲得最高的單線程垃圾收集效率,因此 Serial 垃圾收集器依然是 java 虛擬機運行在 Client 模式下默認的新生代垃圾收集器。

   2.ParNew 垃圾收集器(Serial+多線程)

ParNew 垃圾收集器其實是 Serial 收集器的多線程版本,也使用複製算法,除了使用多線程進行垃 圾收集之外,其餘的行為和 Serial 收集器完全一樣,ParNew 垃圾收集器在垃圾收集過程中同樣也 要暫停所有其他的工作線程。 ParNew 收集器默認開啟和 CPU 數目相同的線程數,可以通過-XX:ParallelGCThreads 參數來限 制垃圾收集器的線程數。ParNew雖然是除了多線程外和Serial 收集器幾乎完全一樣,但是ParNew垃圾收集器是很多 java 虛擬機運行在 Server 模式下新生代的默認垃圾收集器。

  3.Parallel Scavenge 收集器(多線程複製算法、高效)

Parallel Scavenge 收集器也是一個新生代垃圾收集器,同樣使用複製算法,也是一個多線程的垃 圾收集器,它重點關注的是程序達到一個可控制的吞吐量(Thoughput,CPU 用於運行用戶代碼 的時間/CPU 總消耗時間,即吞吐量=運行用戶代碼時間/(運行用戶代碼時間+垃圾收集時間)), 高吞吐量可以最高效率地利用 CPU 時間,儘快地完成程序的運算任務,主要適用於在後台運算而 不需要太多交互的任務。自適應調節策略也是 ParallelScavenge 收集器與 ParNew 收集器的一個 重要區別。

 

老年代:

  4.Serial Old 收集器(單線程標記整理算法 )

Serial Old 是 Serial 垃圾收集器年老代版本,它同樣是個單線程的收集器,使用標記-整理算法, 這個收集器也主要是運行在 Client 默認的 java 虛擬機默認的年老代垃圾收集器。 在 Server 模式下,主要有兩個用途:

    1. 在 JDK1.5 之前版本中與新生代的 Parallel Scavenge 收集器搭配使用。

    2. 作為年老代中使用 CMS 收集器的後備垃圾收集方案。

新生代 Parallel Scavenge 收集器與 ParNew 收集器工作原理類似,都是多線程的收集器,都使 用的是複製算法,在垃圾收集過程中都需要暫停所有的工作線程。

  

  5.Parallel Old 收集器(多線程標記整理算法)

Parallel Old 收集器是Parallel Scavenge的年老代版本,使用多線程的標記-整理算法,在 JDK1.6 才開始提供。 在 JDK1.6 之前,新生代使用 ParallelScavenge 收集器只能搭配年老代的 Serial Old 收集器,只 能保證新生代的吞吐量優先,無法保證整體的吞吐量,Parallel Old 正是為了在年老代同樣提供吞 吐量優先的垃圾收集器,如果系統對吞吐量要求比較高,可以優先考慮新生代 Parallel Scavenge 和年老代 Parallel Old 收集器的搭配策略。

 

  6.Parallel Old 收集器(多線程標記整理算法)

Parallel Old 收集器是Parallel Scavenge的年老代版本,使用多線程的標記-整理算法,在 JDK1.6 才開始提供。 在 JDK1.6 之前,新生代使用 ParallelScavenge 收集器只能搭配年老代的 Serial Old 收集器,只 能保證新生代的吞吐量優先,無法保證整體的吞吐量,Parallel Old 正是為了在年老代同樣提供吞 吐量優先的垃圾收集器,如果系統對吞吐量要求比較高,可以優先考慮新生代 Parallel Scavenge 和年老代 Parallel Old 收集器的搭配策略。

  

  7.CMS 收集器(多線程標記清除算法)

Concurrent mark sweep(CMS)收集器是一種年老代垃圾收集器,其最主要目標是獲取最短垃圾 回收停頓時間,和其他年老代使用標記-整理算法不同,它使用多線程的標記-清除算法。 最短的垃圾收集停頓時間可以為交互比較高的程序提高用戶體驗。

 

 

  8.G1 收集器

Garbage first 垃圾收集器是目前垃圾收集器理論發展的最前沿成果,相比與 CMS 收集器,G1 收 集器兩個最突出的改進是:

    1. 基於標記-整理算法,不產生內存碎片。

    2. 可以非常精確控制停頓時間,在不犧牲吞吐量前提下,實現低停頓垃圾回收。 G1 收集器避免全區域垃圾收集,它把堆內存劃分為大小固定的幾個獨立區域,並且跟蹤這些區域 的垃圾收集進度,同時在後台維護一個優先級列表,每次根據所允許的收集時間,優先回收垃圾 最多的區域。區域劃分和優先級區域回收機制,確保 G1 收集器可以在有限時間獲得最高的垃圾收 集效率。

 

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

【其他文章推薦】

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

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

※回頭車貨運收費標準

※別再煩惱如何寫文案,掌握八大原則!

※超省錢租車方案

分類
發燒車訊

【Spring】@Transactional 閑聊

菜瓜:上次的AOP理論知識看完收穫挺多的,雖然有一個自定義註解的demo,但還是覺得差點東西

水稻:我也覺得沒有跟一遍源碼還是差點意思,這次結合@Transactional註解深入源碼看一下

菜瓜:事務註解,這個平時用的挺多的

水稻:是嗎?來看看你的基礎咋樣

  1. 要保證一個方法中多個數據庫操作的原子性,要共用一個數據庫連接,但是coding時我們不用显示傳遞連接對象,這是咋弄的?
  2. 如果一個方法裏面只有查詢操作,是否不用開啟事務?
  3. 如何解決非事務方法調用本地事務方法失效的?
  4. 註解常用的傳播屬性,你知道他們的區別嗎

菜瓜:雖然沒看過源碼,我大膽猜測一下

  1. 隱式傳遞連接對象可以將其封裝到線程中,一般一次請求操作都是在一個線程中完成。使用ThreadLocal將連接和線程綁定
  2. 查詢操作也得看業務場景,如果多次查詢相同的數據要避免不可重複讀問題,可開啟只讀事務 (readOnly = true)
  3. 結合AOP的知識,這裏其實要解決調用事務方法的對象不是代理對象的問題。用代理對象調本地事務方法即可(注入自己)
    • /**
       * @author QuCheng on 2020/6/24.
       */
      @Service
      public class ItemServiceImpl implements ItemService {
      
          @Resource
          private IcbcItemMapper itemMapper;
      
          @Resource
          private ItemService itemService;
      
          @Override
          public void changeNameById(Long itemId) {
              // changeItemById(itemId);
              itemService.changeItemById(itemId);
          }
      
          @Transactional(rollbackFor = RuntimeException.class)
          @Override
          public void changeItemById(Long itemId) {
              itemMapper.updateNameById(itemId, "name4");
              int a = 10 / 0;
              itemMapper.updatePriceById(itemId, 100L);
          }
      }
  4. 傳播屬性這個沒了解過啊,數據庫事務裏面么得這個概念

水稻:可以啊,平時的代碼沒白寫

菜瓜:coding這種事情,easy啦!

水稻:這就飄了?來看這個問題

  • 如果我想在A事務方法中調用B事務方法,B方法如果回滾了,不能影響A事務繼續執行,但是A事務如果執行出問題了,B也要回滾,怎麼弄?

菜瓜:。。。這不就是大事務嵌套小事務嘛。。。我不會

水稻:不扯了,來看源碼吧,這個問題等解釋了傳播屬性你就知道了

  • 上回我們說到,@Transactional是AOP的典型應用,bean被實例化之後要創建代理(參考自定義註解),就少不了切面類Advisor對象。那麼它是誰,它在哪,它在干什麼?
  • 回到夢開始的地方,事務功能開啟的註解@EnableTransactionManagement
    • 沒錯,它肯定會有一個Import註解引入TransactionManagementConfigurationSelector類,它又引入了切面類
    • public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector<EnableTransactionManagement> {
       
         @Override
         protected String[] selectImports(AdviceMode adviceMode) {
            switch (adviceMode) {
               case PROXY:
                  return new String[] {AutoProxyRegistrar.class.getName(),
                        // 看這裏
                        ProxyTransactionManagementConfiguration.class.getName()};
               case ASPECTJ:
                  return new String[] {determineTransactionAspectClass()};
               default:
                  return null;
            }
         }
      。。。
      
      }
      
      
      @Configuration
      public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {
      
         @Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
         @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
         public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor() {
            BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
            advisor.setTransactionAttributeSource(transactionAttributeSource());
            advisor.setAdvice(transactionInterceptor());
            if (this.enableTx != null) {
               advisor.setOrder(this.enableTx.<Integer>getNumber("order"));
            }
            return advisor;
         }
      
         @Bean
         @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
         public TransactionAttributeSource transactionAttributeSource() {
            return new AnnotationTransactionAttributeSource();
         }
      
         @Bean
         @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
         public TransactionInterceptor transactionInterceptor() {
      // 增強 TransactionInterceptor interceptor
      = new TransactionInterceptor(); interceptor.setTransactionAttributeSource(transactionAttributeSource()); if (this.txManager != null) { interceptor.setTransactionManager(this.txManager); } return interceptor; } } 
    • 切面類對象設置了事務的掃描器,也set了增強類TransactionInterceptor
    • public class TransactionInterceptor extends TransactionAspectSupport implements MethodInterceptor, Serializable {
      。。。
      @Override
          @Nullable
          public Object invoke(MethodInvocation invocation) throws Throwable {
              // Work out the target class: may be {@code null}.
              // The TransactionAttributeSource should be passed the target class
              // as well as the method, which may be from an interface.
              Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);
      
              // Adapt to TransactionAspectSupport's invokeWithinTransaction...
              return invokeWithinTransaction(invocation.getMethod(), targetClass, invocation::proceed);
          }
      }
      
      public abstract class TransactionAspectSupport implements BeanFactoryAware, InitializingBean {
        
      。。。  
      @Nullable
      protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass,
            final InvocationCallback invocation) throws Throwable {
         。。。
      // ①創建事務,數據庫連接處理也在這 TransactionInfo txInfo
      = createTransactionIfNecessary(tm, txAttr, joinpointIdentification); Object retVal = null; try {
      // 調用目標方法 retVal
      = invocation.proceedWithInvocation(); } catch (Throwable ex) {
      // 異常後事務處理 completeTransactionAfterThrowing(txInfo, ex);
      throw ex; } finally { cleanupTransactionInfo(txInfo); } commitTransactionAfterReturning(txInfo); return retVal; } 。。。 } 

菜瓜:懂,接下來的代碼邏輯就是在增強類TransactionInterceptor的invoke方法里

水稻:對

  • 先看數據庫連接的處理 – 驗證ThreadLocal
  • protected void doBegin(Object transaction, TransactionDefinition definition) {
       。。。
    // 如果連接是新的,就進行綁定
    if (txObject.isNewConnectionHolder()) { TransactionSynchronizationManager.bindResource(this.obtainDataSource(), txObject.getConnectionHolder()); } 。。。 } class TransactionSynchronizationManager public static void bindResource(Object key, Object value) throws IllegalStateException { Object actualKey = TransactionSynchronizationUtils.unwrapResourceIfNecessary(key); Assert.notNull(value, "Value must not be null"); Map<Object, Object> map = resources.get(); // set ThreadLocal Map if none found if (map == null) { map = new HashMap<>(); resources.set(map); } Object oldValue = map.put(actualKey, value); // Transparently suppress a ResourceHolder that was marked as void... if (oldValue instanceof ResourceHolder && ((ResourceHolder) oldValue).isVoid()) { oldValue = null; } if (oldValue != null) { throw new IllegalStateException("Already value [" + oldValue + "] for key [" + actualKey + "] bound to thread [" + Thread.currentThread().getName() + "]"); } if (logger.isTraceEnabled()) { logger.trace("Bound value [" + value + "] for key [" + actualKey + "] to thread [" + Thread.currentThread().getName() + "]"); } }
  • 回過頭來看AB方法調用的回滾問題,直接給出答案(突然發現這個問題要講清楚篇幅會很大,就。。挺突然的。。挺突然der)
    • 在B方法上設置傳播屬性為NESTED即可,然後在A中catch住B的異常
    • 你肯定會問我不加NESTED去catch不行嗎?不行,非NESTED的方法拋出的異常是無法回滾的。
    • 不信你看
    • @Transactional(rollbackFor = RuntimeException.class)
          @Override
          public void changeNameById(Long itemId) {
              itemMapper.updateNameById(itemId, "A");
              try {
                  itemService.changeItemById(itemId);
      //            itemService.changeItemByIdNested(itemId);
              } catch (Exception e) {
                  System.out.println("我想繼續執行,不影響修改A");
              }
              itemMapper.updatePriceById(itemId, 1L);
          }
      
          @Transactional(rollbackFor = RuntimeException.class)
          @Override
          public void changeItemById(Long itemId) {
              itemMapper.updateNameById(itemId, "B+REQUIRED");
              itemMapper.updatePriceById(itemId, 10L);
              int a = 10 / 0;
          }
      
          @Transactional(rollbackFor = RuntimeException.class, propagation = Propagation.NESTED)
          @Override
          public void changeItemByIdNested(Long itemId) {
              itemMapper.updateNameById(itemId, "B+NESTED");
              itemMapper.updatePriceById(itemId, 100L);
              int a = 10 / 0;
          }
      
      
      -- 測試結果
      //①  itemService.changeItemById(itemId);  數據庫所有數據都不會改變
      我想繼續執行,不影響修改A
      org.springframework.transaction.UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only
      
      // ② itemService.changeItemByIdNested(itemId); 第一個方法的修改會生效
      我想繼續執行,不影響修改A

菜瓜:這就是傳播屬性NESTED?默認的是REQUIRED,還有一個常用的REQUIRES_NEW呢?

水稻:搞清楚這個其實從數據庫連接入手其實就很清楚

  • REQUIRED修飾的方法和A使用同一個連接,A和B是掛一起的,誰回滾都會影響對方,且B方法的異常會被事務管理器標記為必須回滾
  • NESTED修飾的方法和A使用同一個連接,但是用到了數據庫的savePoint特性,它可以回滾到指定的點,如果是有回滾點的操作,拋出的異常可以被處理
  • REQUIRES_NEW修飾的方法和A使用的就不是一個連接了,回不回滾都不會影響對方,當然,要捕捉異常

菜瓜:傳播屬性了解。回滾的問題還得再看看,篇幅很大是很複雜嗎?

水稻:其實不複雜,就是要跟蹤源碼斷點調試。。。截圖搞來搞去,篇幅就很長,你自己去調的話其實很快

菜瓜:那我下去康康

 

總結

  • 這裏提到Transactional註解其實是為了鞏固AOP的,當然提到了一些注意點。譬如本地調用,譬如ThreadLocal的應用,還譬如傳播屬性
  • 傳播屬性其實用的少,但是聊起來就比較多了,可以聊事務的隔離級別,聊ACID的實現,聊MySQL的鎖

 

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

【其他文章推薦】

※超省錢租車方案

※別再煩惱如何寫文案,掌握八大原則!

※回頭車貨運收費標準

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

分類
發燒車訊

三年增15萬個 北京2016年電動車搖號指標將占四成

26日北京市人大常委會會議表示,北京將逐步提高北京市小客車搖號指標中電動車的數量,未來三年分別新增3萬、6萬、6萬輛。到2016年電動車指標將占所有搖號指標的40%。   2011年起,北京開始實施小客車總量調控政策,將每年新增指標控制在24萬輛。2014年,這一數位進一步壓縮到15萬輛。目前,北京市機動車保有量已經超過500萬輛。北京市提出,將在每年15萬輛小客車新增指標內逐步提高電動車的數量。

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

【其他文章推薦】

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

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

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

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

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

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

分類
發燒車訊

中國政策放開電動車准入要求 小米或入局電動車

11月26日,國家發改委網站掛出《新建純電動乘用車生企業投資項目和生產準入管理的暫行規定(徵求意見稿)》(以下簡稱《規定》),計劃為純電動車生準入放開口子。   《規定》要求的三條基礎能力中,最核心的是:(申報企業)有3年以上純電動乘用車的研發基礎,具有專業研發團隊和整車正向研發能力,掌握整車控制系統、動力電池系統、整車整合和整車輕量化方面的核心技術以及相應的試驗驗證能力,擁有純電動乘用車自主智慧財產權和已授權的相關發明專利。另外還要求新建企業只能生產純電動轎車和純電動其他乘用車(包括增程式電動乘用車),插電式混合動力不在準入範圍內。   面對新一批電動車開放名單,包括小米、樂視與萬向等企業集團都展現出高度興趣,爭取成為入圍名單。其中小米的動向最受矚目。小米創辦人之一黎萬強早在10月底就悄悄飛往矽谷展開暖身動作,小米董事長雷軍更在拜會特斯拉後就對電動車念念不忘。事實上,小米電動車的諜照早就在網路上曝光,只是細節外界所知不多。不過,這次開放的限制很嚴,小米能否如願以償擠進電動車窄門,備受關注。   (照片來源: )

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

【其他文章推薦】

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

網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

南投搬家公司費用,距離,噸數怎麼算?達人教你簡易估價知識!

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

※超省錢租車方案

分類
發燒車訊

面試官:你剛說你喜歡研究新技術,那麼請說說你對 Blazor 的了解

閱讀本文大概需要 1.5 分鐘。

最近在幾個微信 .NET 交流群里大家討論比較頻繁的話題就是這幾天自己的面試經歷。

面試官:“你剛說你喜歡研究新技術,那麼你對 Blazor 了解多少?”。

作為一位專註於 .NET 開發的軟件工程師,你好意思說你對 Blazor 一點也不解嗎?.NET 新技術也就是那麼幾個,連微軟最近在逛推的 Blazor 你都不了解,你好意思說你喜歡研究新技術?

講真,確實有很多童鞋對 Blazor 還不了解,平時埋頭寫代碼改 Bug,哪有時間去研究 Blazor,再說這種玩意兒公司會不會採用還是個很大疑問呢。是這個理,但如果等你的公司(國內使用了.NET 技術的公司)都開始使用 Blazor 了,Blazor 還能算是新技術嗎?出於真正對技術的興趣和熱愛,對於新技術,有人會主動地去了解(不一定要研究得很深),而不是等到需要用的時候再去了解。至少他們會知道新技術有哪些優點,在公司技術選型上就可以給到自己的意見甚至推廣新技術的使用,這可能就是他們和普通程序員拉開差距的原因之一。

不管你是真對 Blazor 感興趣,還是只是為了應付面試,作為 .NET 開發者,你沒用過 Blazor,至少應該了解一下吧,哪怕是花個一兩分鐘看看這篇文章的介紹。

使用 C# 實現 Web 交互式 UI

Blazor 允許你使用 C# 來實現 Web 交互式 UI,而不需要使用 JavaScript。儘管 JavaScript 的生態很強大,但這種弱類型語言在業務邏輯比較複雜的大型 Web 開發上還是存在較大的缺陷。當然,經過幾年的發展 JavaScript 的弱類型問題可以通過工程手段來解決,甚至使用 TypeScript 來替代,但在實現可重用組件上還是有諸多的不理想。

Blazor 應用可以使用 C#、HTML 和 CSS 實現可重用 Web UI 組件,客戶端和服務器代碼都用 C# 編寫的,允許你共享代碼和庫。Blazor 是 ASP.NET Core 的一個新特性,所以可以很好的集成到 ASP.NET Core MVC/Razor Pages 應用中。

下面是一段來自於模板的 Blazor 代碼:

@page "/counter"

<h1>Counter</h1>

<p>Current count: @currentCount</p>

<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>

@code {
    private int currentCount = 0;

    private void IncrementCount()
    {
        currentCount++;
    }
}

在 WebAssembly 或服務器端運行

Blazor 支持兩種運行方式,一是在客戶端使用 WebAssembly 運行,二是在服務器端運行直接渲染到瀏覽器。

Blazor 可以使用 WebAssembly 直接在瀏覽器中運行客戶端 C# 代碼,正因為它是運行在 WebAssembly 上的 .NET 程序,所以客戶端也可以重用服務器端的代碼和庫。

即使不使用 WebAssembly,Blazor 也可以在服務器端運行客戶端的業務邏輯。客戶端 UI 事件使用實時消息框架 SignalR 發送回服務器,一旦執行完成,所需的 UI 更改將發送到客戶端渲染到 DOM 中。

目前主流開發單頁應用(SPA)使用 Vue 或 React 的很多,但要實現服務器端渲染(SSR),還是挺麻煩的,儘管有現成的像 Next.js 或 Nuxt.js 這樣的框架可以使用,但由於它們更新迭代比較快,依賴的 npm 包多而雜,後期維護和升級成本也很高。所以從 SSR 支持這一點來講,Blazor 應用還是有明顯優勢的。

基於開放的 Web 標準

通常是為了使用統一的編程語言或使用統一的標準,常見的做法是將一種編程語言編寫的代碼轉換為另一種編程語言,比如將 TypeScript 編寫代碼轉換成 JavaScript 以便在瀏覽器中運行。而 Blazor 使用的是開放的 Web 標準,不需要額外的插件或代碼語言轉換。Blazor 可以在所有主流的 Web 瀏覽器中工作,包括移動端瀏覽器。

在客戶端運行 Blazor 代碼和 JavaScript 框架一樣是在安全的沙箱中執行的,在基於開放的 Web 標準基礎上,Blazor 具有服務器端代碼的靈活性,比如直接連接數據庫。

和 JavaScript 交互

在 Blazor 應用中,你可以在 C# 代碼中調用 JavaScript 代碼,也可以在 JavaScript 代碼中調用 C# 代碼,兩者可以很容易實現交互操作。好處是,在使用 C# 編寫業務代碼時,你依然可以繼續使用現有龐大的 JavaScript 庫生態系統。當使用服務器端運行代碼時,Blazor 會負責在客戶端使用 JavaScript 無縫調用 C# 代碼。

下面是一個 JavaScrit 調用 C# 的示例[2]

先使用 JSInvokable 特性標註一個 C# 方法為允許 JavaScript 調用:

<button type="button" class="btn btn-primary"
        onclick="exampleJsFunctions.returnArrayAsyncJs()">
    Trigger .NET static method ReturnArrayAsync
</button>

@code {
    [JSInvokable]
    public static Task<int[]> ReturnArrayAsync()
    {
        return Task.FromResult(new int[] { 1, 2, 3 });
    }
}

然後在 JavaScript 代碼中調用 C# 代碼:

window.exampleJsFunctions = {
  ...
  returnArrayAsyncJs: function () {
    DotNet.invokeMethodAsync('BlazorSample', 'ReturnArrayAsync')
      .then(data => {
        data.push(4);
          console.log(data);
      });
  },
  ...
};

其它

對我來說 Blazor 最吸引的優點是前後端代碼的共用以及組件的重用。通過 nuget 管理包不僅比 npm 方便,而且體積也小很多。

Blazor 的生態也正逐步發展起來了,雖然還沒有聽說哪個大公司在用,但 Blazor 的理念是未來趨勢,值得你花點時間了解和研究一下。

參考:

[1]. http://dwz.win/EU4
[2]. http://dwz.win/EU3

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

【其他文章推薦】

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

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

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

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

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

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

分類
發燒車訊

擴張的撒哈拉沙漠 破碎的家庭和暴力

環境資訊中心綜合外電;姜唯 編譯;林大利 審校

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

【其他文章推薦】

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

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

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

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

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

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

分類
發燒車訊

菲律賓民答那峨島發生規模6.6強震

摘錄自2019年10月16日上報、29日自由時報報導

根據美國地質調查所(USGS)觀測顯示,菲律賓民答那峨島當地時間29日早9時許傳出規模6.6強震。震央位於民答那峨島的達沃市(Davao City)東南方,地震深度僅15.3公里。

截至下午4:00為止,麥格塞塞(Magsaysay)鎮發言人告訴法新社,一名十多歲的男學生逃離校舍時,遭倒下的牆壓死。另有學生在逃出教室時因「踩踏」受傷,所幸保住性命。 科羅納達爾(Koronadal)鎮當局也表示,當地一名66歲男性被倒下的牆壓死。 截至目前至少有50人遭掉落的瓦礫砸傷,包括一所小學的7名師生在逃離校舍時受傷。

本月16日,一場規模6.4的淺層強震才襲擊菲律賓南部,至少1人受傷。根據美國地質調查所,震源深度14公里,震央距離民答那峨島哥倫比歐市(Columbio)約7.7公里。地震發生於當地時間晚間7時37分。其中,基達帕灣市(Kidapawan City)達7級震度,預計仍會有餘震,該市市長宣布17日全面停課。

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

【其他文章推薦】

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

網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

南投搬家公司費用,距離,噸數怎麼算?達人教你簡易估價知識!

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

※超省錢租車方案

分類
發燒車訊

巴黎共享滑板車亂象多 河中打撈竟成新興工作

摘錄自2019年10月26日民視新聞報導

巴黎目前有十多家業者、提供了大概2萬輛電動滑板車,可以自由租借,帶來方便的同時,也帶來了混亂,街頭隨處可見被人亂停、亂丟的電動滑板車,還有不少直接被扔進塞納河。負責清理、回收這些電動滑板車的「巡邏隊」,成了新興工作。

塞納河畔有人用力拉著繩索,他們可不是在釣魚,而是在「釣電動滑板車」,這家電動滑板車公司的員工,3個鐘頭從河裡打撈了足足15輛。電動滑板車公司員工表示:「就像那輛的手把卡在岸邊,我們不可能直接把它拉起來,你必須下到水裡,把手把轉向才能將它弄起來。」

 

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

【其他文章推薦】

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

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

※別再煩惱如何寫文案,掌握八大原則!

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

※超省錢租車方案

分類
發燒車訊

三菱插電式混動新技術 可為家庭供電

日前,日本三菱汽車公司宣佈,其歐藍德插電式混合動力汽車(PHEV)將配置V2H電動汽車家庭供電系統,其電池儲存的電量可以支援家庭供電的不時之需。此前V2H供電系統僅用於類似i-MIEV之類的純電動汽車。據悉,歐藍德PHEV搭載2.0升汽油發動機與一台電動馬達,可以以60英里每小時的速度行駛30英里,總續航里程可達540英里。

三菱的V2H系統在自然災害或停電的時候,可以作為100伏特(日本規格)的家用供電電源使用,運用1500瓦的交流電源,滿足家用需求。僅電池電量可以滿足普通家庭一天的用電需求。如果加滿汽油,其總電量或將滿足一個普通家庭將近10天的用電需求。

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

【其他文章推薦】

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

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

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

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

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

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

分類
發燒車訊

不畏油價跌 美電動車 12 月創最高單月銷售紀錄

儘管美國汽油零售價格跟隨國際原油同步下挫到每加侖 2 美元的低水準,2014 年美國電動車銷售強勁增加 23%,12 月並創下單月最佳紀錄;顯見電動車已蔚為一股持久的趨勢,不受油價影響。   根據電動車專業網站 InsideEVs 統計,2014 年 12 月美國賣出 12,874 輛電動車,為統計以來最高單月銷售紀錄。至於 2014 年全年,電動車銷售勁揚 23%,達到 119,710 輛。   就個別品牌來看,全美電動車銷售冠軍是日產 Leaf,2014 年總計售出 30,200 輛,遙遙領先亞軍通用汽車雪佛蘭 Volt 的 18,805 輛。起價介於 3.5 萬到 4 萬美元的特斯拉 Model S 排名第 3,全年銷量為 17,300 輛,市占不及 15%。不過,在 12 月 Model S 首度擊敗售價較低的日產 Leaf(約 3 萬美元)。   2014 年美國電動車市場唯一新上市車款是 BMW,分別在 5 月及 8 月推出 i3 與 i8 ,加總的銷量僅 6,647 輛。展望 2015 年,將有數款新型電動車上路,尤其是在休旅車和越野車市場。而特斯拉的 Model X 則預計 2015 年下半年登場,是今年最受期待的電動車。

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

【其他文章推薦】

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

網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

南投搬家公司費用,距離,噸數怎麼算?達人教你簡易估價知識!

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

※超省錢租車方案