多線程之美1一volatile

目錄
一、java內存模型
1.1、抽象結構圖
1.2、概念介紹
二、volatile詳解
2.1、概念
2.2、保證內存可見性
2.3、不保證原子性
2.4、有序性

一、java內存模型

1.1、抽象結構圖

1.2、概念介紹

  • java 內存模型

    即Java memory model(簡稱JMM), java線程之間的通信由JMM控制,決定一個線程對共享變量的寫入何時對另一個線程可見。
  • 多線程通信通常分為2類:共享內存和消息傳遞

     JMM採用的就是共享內存來實現線程間的通信,且通信是隱式的,對程序開發人員是透明的,所以在了解其原理了,才會對線程之間通信,同步,內存可見性問題有進一步認識,避免開發中出錯。
  • 線程之間如何通信?

    在java中多個線程之間要想通信,如上圖所示,每個線程在需要操作某個共享變量時,會將該主內存中這個共享變量拷貝一份副本存在在自己的本地內存(也叫工作內存,這裏只是JMM的一個抽象概念,即將其籠統看做一片內存區域,用於每個線程存放變量,實際涉及到緩存,寄存器和其他硬件),線程操作這個副本,比如 int i = 1;一個線程想要進行 i++操作,會先將變量 i =1 的值先拷貝到自己本地內存操作,完成 i++,結果 i=2,此時主內存中的值還是1,在線程將結果刷新到主內存后,主內存值就更新為2,數據達到一致了。
    
    如果線程A,線程B同時將 主內存中 i =1拷貝副本到自己本地內存,線程A想要 將i+1,而線程B想要將 int j=i,將賦值給j,那麼如何保證線程之間的協作,此時就會涉及到線程之間的同步以及內存可見性問題了。(後文分析synchronized/lock)
     那線程之間實現通信需要經過2個步驟,藉助主內存為中間媒介:
       線程A (發送消息)-->(接收消息) 線程B  
       1、線程A將本地內存共享變量值刷新到主內存中,更新值;
       2、線程B從主內存中讀取已更新過的共享變量;
  • 共享內存中涉及到哪些變量稱為共享變量?

    這裏的共享內存指的是jvm中堆內存中,所有堆內存在線程之間共享,因為棧中存儲的是方法及其內部的局部變量,不在此涉及。
    共享變量:對於多線程之間能夠共同操作的變量,包含實例域,靜態域,數組元素。即有成員變量,靜態變量等等,
       不涉及到局部變量(所以局部變量不涉及到內存可見性問題)
  • 多線程在java內存模型中涉及到三個問題

    • 可見性
    • 原子性
    • 有序性(涉及指令重排序)

二、volatile詳解

2.1、概念

-1、volatile 是 java中的關鍵字,可修飾字段,可以保證共享變量的在內存的可見性,有序性,不保證原子性。
-2、作用:在了解java內存模型后,才能更加了解volatile在JMM中的作用,volatile在JMM中為了保證內存的可見性,即是線程之間操作共享變量的可見性。
  • volatile寫和讀的內存語義
volatile 寫的內存語義:
    當寫一個volatile修飾的共享變量時,JMM會把該線程的本地內存的共享變量副本值刷新到主內存中;
volatile 讀的內存語義:
    當讀一個volatile修飾的共享變量時,JMM會將該線程的本地內存的共享變量副本置為無效,要求線程重新去主內存中獲取最新的值。
  • java內存模型控制與volatile衝突嗎?什麼區別?
不衝突!java內存模型控制線程工作內存與主內存之間共享變量會同步,即線程從主內存中讀一份副本到工作內存,又刷新到主內存,那怎麼還需要 volatile來保證可見性,不是JMM自己能控制嗎,一般情況下JMM可以控制 2份內存數據一致性,但是在多線程併發環境下,雖然最終線程工作內存中的共享變量會同步到主內存,但這需要時間和觸發條件,線程之間同時操作共享變量協作時,就需要保證每次都能獲取到主內存的最新數據,保證看到的工作變量是最後一次修改后的值,這個JMM沒法控制保證,這就需要volatile或者後文要講的 synchronized和鎖的同步機制來實現了。

2.2、保證內存可見性

  • 1、多個線程出現內存不可見問題示例

    /**
     * @author zdd
     * Description: 測試線程之間,內存不可見問題
     */
    public class TestVisibilityMain {
        private static boolean isRunning = true;
    
      // 可嘗試添加volatile執行,其餘不變,查看線程A是否被停止
      //private static volatile boolean isRunning = true;
    
        public static void main(String[] args) throws InterruptedException {
    //1,開啟線程A,讀取共享變量值 isRunning,默認為true 
            new Thread(()->{
              // --> 此處用的lamda表達式,{}內相當於Thread的run方法內部需執行任務 
                System.out.println(Thread.currentThread().getName() + "進入run方法");
                while (isRunning == true) {
                }
                System.out.println(Thread.currentThread().getName()+"被停止!");
            },"A").start();
            //2,主線程休眠1s, 確保線程A先被調度執行
            TimeUnit.SECONDS.sleep(1);
        //3,主線程修改共享變量值 為flase,驗證線程A是否能夠獲取到最新值,跳出while循環  --> 驗證可見性
            isRunning =false;
            System.out.println(Thread.currentThread().getName() +"修改isRunning為: " + isRunning);
        }
    }

​ 執行結果如下圖:

  • 2、一個容易忽視的問題
 上面代碼 while裏面是一個空循環,沒有操作,如果我在裏面加一句打印語句,線程A會被停止,這是怎麼回事呢?
 原:while (isRunning == true) {}
 改1:
 while (isRunning == true) {
     System.out.println("進入循環");
 }
原來 println方法裏面加了 synchronized關鍵字,在加了鎖既保證原子性,也保證了可見性,會實現線程的工作內存與主內存共享變量的同步。
源代碼如下:
 public void println(String x) {
        synchronized (this) {
            print(x);
            newLine();
        }
    }
  改2:
  while (isRunning == true) {
       //改為這樣,也可以停止線程A
                synchronized (TestVisibilityMain.class){}
   }

2.3、不保證原子性

  • 1、示例代碼
/**
 * @author zdd
 * Description: 測試volatile的不具有原子性
 */
public class TestVolatileAtomic {

    private static volatile   int  number;
    //開啟線程數
    private static final  int THREAD_COUNT =10;
    //執行 +1 操作
    public static void  increment() {
       //讓每個線程進行加1次數大一些,能夠更容易出現volatile對複合操作(i++)沒有原子性的錯誤
        for (int i = 0; i < 10000; i++) {
          number++;
        }
        System.out.println(Thread.currentThread().getName() +"的number值: "+number);
    }

    public static int getNumber() {
        return number;
    }

    public static void main(String[] args) throws InterruptedException {
        TestVolatileAtomic volatileAtomic  = new TestVolatileAtomic();
        Thread[] threads = new Thread[THREAD_COUNT];
        for (int i = 0; i < THREAD_COUNT; i++) {
            threads[i]=
            new Thread(()->{
               // 做循環自增操作
                volatileAtomic.increment();
                System.out.println(Thread.currentThread().getName() +"的number值: "+volatileAtomic.getNumber());
            },"thread-"+i);
        }

        for (int i = 0; i <10; i++) {
          //開啟線程
            threads[i].start();
        }
        //主線程休眠4s,確保上麵線程都執行完畢
        TimeUnit.SECONDS.sleep(4);
        System.out.println("執行完畢,number最終值為:"+volatileAtomic.getNumber());
    }
}

執行結果:number的最後值不一定是 10*10000= 100000的結果
  • 2、解決上訴問題
 
  //1,increment()方法上加上 synchronized關鍵字同步
    public static synchronized void  increment() {
       //讓每個線程進行加1次數大一些,能夠更容易出現volatile對複合操作(i++)沒有原子性的錯誤
        for (int i = 0; i < 10000; i++) {
          number++;
        }
         System.out.println(Thread.currentThread().getName() +"的number值: "+number);
    }
  //2,使用Lock,使用其實現類可重入鎖 ReentrantLock
    static Lock lock = new ReentrantLock();
    //執行 +1 操作
    public static   void  increment() {
        lock.lock();
        try {
            for (int i = 0; i < 10000; i++) {
                number++;
            }
            System.out.println(Thread.currentThread().getName() + "的number值: " + number);
        } finally {
            lock.unlock();
        }
    }

運行結果如圖:

  • 3、原因分析
對單個volatile變量的讀/寫具有原子性,而對像 i++這種複合操作不具有原子性。
上面代碼 i++操作可以分為3個步驟
-1 先讀取變量i的值   i
-2 進行i+1操作   temp= i+1
-3 修改i的值     i= temp
比如:比如在線程A,B同時去操作共享變量i, i的初始值為10,A,B同時去獲取i的值,A對i進行 temp =i+1,此時i的值還沒變, 線程B也對i進行 temp=i+1了,線程A執行i=temp的操作,i的值變為11,此時由於 volatile可見性,會刷新A的 i值到主內存,主內存中i此時也更新為11了,線程B接收到通知自己i無效了,重新讀取i=11,雖然i=11,但是已經進行過 temp= i+1了,此時temp =11,線程B繼續第三步,i=temp =11, 預期結果是i被A,B自增各一次,結果i=12,現在為11,出現數據錯誤。

2.4、有序性

  • 重排序
-1,重排序概念:重排序是編譯器和處理器為了優化程序性能而對指令序列重新排序的一種手段
即:程序員編寫的程序代碼的順序,在實際執行的時候是不一樣的,這其中編譯器和處理器在不影響最終執行結果的基礎上會做一些優化調整,有重新排序的操作,為了提高程序執行的併發性能。
-2,重排序分類: 編譯重排序,處理器重排序
-4,單線程下,重排序沒有問題,但是在多線程環境下,可能會破壞程序的語義.
  • volatile 防止重排序保證有序性

為了實現volatile的內存語義,JMM會限制編譯器和處理器重排序

-1 制定了重排序規則表防止編譯器重排序

volatile重排序規則表(圖摘自書-併發編程的藝術)

-2 插入內存屏障防止處理器重排序

參考資料:
1、Java併發編程的藝術- 方騰飛
2、java多線程編程核心技術- 高洪岩

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

【其他文章推薦】

※想知道網站建置網站改版該如何進行嗎?將由專業工程師為您規劃客製化網頁設計後台網頁設計

※不管是台北網頁設計公司台中網頁設計公司,全省皆有專員為您服務

※Google地圖已可更新顯示潭子電動車充電站設置地點!!

※帶您來看台北網站建置台北網頁設計,各種案例分享

傳染病專家稱寵物會感染武漢肺炎 WHO:目前沒有證據

摘錄自2020年1月30日ETtoday報導

2019新型冠狀病毒(武漢肺炎)疫情延燒,中國傳染病診治國家重點實驗室主任、國家衛健委高級別專家組成員李蘭娟29日接受央視訪問,針對網友熱烈詢問的問題進行解答,其中包含武漢肺炎病患二次感染的機會,還有人類是否會將病毒傳染給寵物等問題。針對這些問題她表示,二次感染機會很小,而人與寵物間是有可能相互傳染的。

此番言論引起熱烈討論,許多大陸網友聽聞後,擔憂流浪貓狗會遭到撲殺,紛紛呼籲飼主不可隨便棄養,要有防範的意識與準備。

針對李蘭娟此番言論,世界衛生組織(WHO)晚間7點緊急在官方微博指出,目前沒有證據顯示貓狗等寵物會感染新型冠狀病毒,人類在與寵物接觸後,只要用肥皂洗手就可以減少常見的細菌在兩者間傳播。

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

【其他文章推薦】

※想知道網站建置網站改版該如何進行嗎?將由專業工程師為您規劃客製化網頁設計後台網頁設計

※不管是台北網頁設計公司台中網頁設計公司,全省皆有專員為您服務

※Google地圖已可更新顯示潭子電動車充電站設置地點!!

※帶您來看台北網站建置台北網頁設計,各種案例分享

對於計算機相關專業我們在迷茫什麼

計算機相關專業初識–對於計算機相關專業我們在迷茫什麼

前言

由於種種原因,迫使我寫下這篇博客,我相信,初入計算機相關專業的萌新肯定很迷茫,我該學什麼,我該如何去學,我該如何學好等等問題纏繞心頭。有很多學弟學妹問我該如何去學計算機相關專業,作為過來人,我決定將我的所知所得寫下來,讓初入計算機相關專業的萌新的學習之路走得更順暢一些。

一、什麼是計算機

對於剛學習計算機相關專業的萌新來說,了解一下計算機的工作原理是十分必要的,但是在這裏我們不過多闡述,讓大家簡單了解一下就好。

讓我們先來看一下對於計算機名詞的解釋:

計算機(computer)俗稱電腦,是現代一種用於高速計算的电子計算機器,可以進行數值計算,又可以進行邏輯計算,還具有存儲記憶功能。是能夠按照程序運行,自動、高速處理海量數據的現代化智能电子設備。

划重點:

  • 我們注意到,計算機就是一種用於進行數值計算的現代化智能电子設備。需要理解的是為什麼是進行數值計算,在這裏,你會疑惑,為什麼是數值計算呢,我輸入的明明不是数字呀?這個問題很容易解釋清楚,因為計算機只是一種电子設備,它不具有人類獨立思考和不斷學習的能力,它的所有功能都是事先設定好的,所以當計算機面對輸入字符的時候,會將它統一按照ASCII(計算機編碼系統)規則轉換為數值“0”和“1”(二進制數值),所以,在計算機里,數據存儲都是用“0”和“1”(即二進制數值)來實現。

  • 還有一點值得注意,按照程序運行,那麼問題來了,程序是什麼?程序就是一組計算機能識別和執行的指令, 它以某些程序設計語言編寫,運行於某種目標結構體繫上 。舉個例子,程序就像是用英語(程序設計語言,例如c,c++)寫的文章,要讓一個懂的英語的人(編譯器,如C的編譯器gcc,這裏要注意編譯器和IDE的區別,通常IDE包含編譯器)同時也會閱讀這篇文章的人(結構體系)來閱讀、理解、標記這篇文章。

有學妹問過我,為什麼簡單的代碼,能實現豐富的效果。其實這取決於編譯器的強大能力。下面來簡單介紹一下,編輯器,編譯器,IDE(集成開發環境)的區別。

  • 編輯器:編輯器就是用來編輯的軟件,比如windows自帶的記事本就是一個編輯器, 記事本沒有語法高亮,不显示行號,當一段可執行代碼寫完后無法通過內置環境執行,必須手動輸入命令執行編譯等等一些弊端,所以很少有程序員會用記事本去寫代碼 , 寫代碼比較好用的編輯器軟件有vscode,vim,sublime,notepad++,emacs,atom等等 ,雖然編輯器原始功能不足,但是開發人員為了使編輯器更加友好,所以有很多內置插件可供使用,完全可以手動打造一個IDE。
  • 編譯器:簡單來說,編譯器就是將“一種語言(一般為高級語言,如c,c++,java,python等,計算機不可直接識別和執行)”翻譯為“另一種語言(一般為低級語言,低級語言即機器語言,機器語言是用二進制代碼錶示的計算機能直接識別和執行的一種機器指令的集合)”的程序。舉個例子,用Dev-C++寫好一段可執行"hello,world!"C語言代碼之後,我們要讓它在屏幕打印出來我們想要它輸出的"hello,world!",就需要通過gcc編譯器執行編譯后才能显示。其他語言同理。
  • IDE:集成開發環境,用於程序開發環境的應用程序,一般包含代碼編輯器編譯器調試器圖像用戶界面等工具。集成了代碼編寫程序分析程序編譯程序調試等功能。如 jetbrains 的用於Java開發的 IntelliJ IDEA 、用於JavaScript開發的WebStorm、用於Python開發Pycharm,微軟的 Visual Studio系列 ,IBM的Eclipse。

二、我們該學什麼

很多初入計算機相關專業的萌新,總是很迷茫,不知道自己該學什麼,通常是他們知道如何去學好學校開設的每一門課程,就是不知道自己該向哪些方向學習,這些方向指的是專業技能和就業方向,諸如web開發、Android/IOS開發、數據分析、人工智能、網絡安全、遊戲開發、軟件測試等等。有這種疑惑很正常,迷茫也是正常的,但我們總要讓自己了解自己所需,然後腳踏實地,一步一步去充實自己的能力。而我想做的也很簡單,就是幫助大家解除心裏的疑惑。那麼,我們開始進入正題。

1. 我們該如何選擇適合自己的方向

對於這個問題,其實是很難回答清楚的,因為每個人的興趣都不相同,所以就很難去站在自己的角度去回答疑問者的問題。但是,原理都是想通的,我相信我的經驗會幫助到你們。

  • 通常,學校每學期都會開設一門或多門語言(程序設計語言,下文同),那麼,喜歡一門語言,首先要愛上它的語言風格,諸如Java的嚴謹,Python的自由,總有一款適合你;其次,在學習語言的過程中,一定要了解它能幹什麼,市場環境如何,工作崗位多少等綜合因素,再決定要不要去深入這門語言,並且主攻自己感興趣的那個方向。

  • 對於學校沒有開設,但是自己又想學習的語言而言,該如何去選擇。首先,學校開設的語言基本是市場比較流行的語言,也符合市場需求,所以,完全可以在學校開設的語言中去選擇自己想要了解並學習的語言。此外,我們可以藉助 TIOBE ( TIOBE 編程社區指數是編程語言流行度的指標,該榜單每月更新一次,指數基於全球技術工程師、課程和第三方供應商的數量。包括流行的搜索引擎,如谷歌、必應、雅虎、維基百科、亞馬遜、YouTube 和百度都用於指數計算。 )去了解語言的流行程度,流行程度決定市場需求,以此來參考自己想要了解並學習的語言,在此附上2019年11月語言排名。

2. 主流編程語言主要應用場景

  • Java

    1. 企業級應用開發: 大到全國聯網的系統,小到中小企業的應用解決方案,Java都佔有極為重要的地位 。
    2. web後端開發: JSP+Servlet+JavaBean 是一種比較流行的開發模式。
    3. 移動領域:手機遊戲。
    4. Android App開發: android 開發只用到了JAVA的語法和JAVA SE的一小部分API。
  • C

    C語言是一門基礎語言,是其他一些語言的基礎,例如MATLAB,Object-C,Lua等.同時也是學習來比較難的語言,達到精通的程度沒有3-10年左右很難,C語言沒有比較完善的開發框架,是面向過程的一門語言,講究算法跟邏輯。

    1. 科研
    2. 服務器: 網絡核心設備,如路由器、交換機、防火牆。
    3. 操作系統:類unix系統(Linux/freebsd)
    4. 嵌入式開發: 在一個特定的硬件環境上開發與構建特定的可編程軟件系統的綜合技術。
    5. 自動化控制
  • Python

    1. 圖形處理
    2. 數學處理
    3. 文本處理
    4. 數據庫編程
    5. 網絡編程
    6. 多媒體應用
    7. pymo引擎: 運行於Symbian S60V3,Symbian S60V5,Symbian 3,Android,Windows,Linux,Mac Os,Maemo,MeeGo系統上的AVG遊戲引擎。
    8. 黑客編程
    9. 網絡安全
  • C++

    1. 遊戲開發
    2. 科學計算
    3. 網絡軟件
    4. 操作系統
    5. 設備驅動程序
    6. 移動設備
    7. 嵌入式開發
    8. 科研
    9. 編譯器
  • C#

    1. web後端開發
    2. 桌面軟件開發
    3. 人工智能
    4. 遊戲開發
  • JavaScript
    唯一能用於前後端開發的語言web前端開發
    1. web前端開發
    2. node web後端開發
    3. 操作系統
    4. 後台
    5. 桌面軟件開發
    6. 混合App
    7. 小程序
  • PHP

    1. web後端開發
    2. 桌面軟件開發
    3. 命令行腳本
  • SQL

    1. 操作數據庫
  • Swift

    1. 蘋果生態系統應用開發
  • Ruby

    1. web開發
  • R

    數據科學闖天下,左手Python右手R

    1. 機器學習
    2. 數據分析
    3. 科學計算
  • Go

    1. web後端開發
    2. 高性能服務器應用

3. 主流編程語言學習路徑(將持續更新,僅供參考)

  • JavaScript

4. 主流編程語言入門學習書籍推薦

語言 書籍
C 《嗨翻C語言》
C++ 《C++權威教程》
Java 《Java輕鬆學》
Python 《Python編程從入門到實戰》
JavaScript 《JavaScript入門經典》
PHP 《PHP編程實戰》
SQL 《SQL基礎教程》
Swift 《Swift編程權威指南》
Ruby 《Ruby從入門到精通》
R 《R語言實戰》
Go 《Go語言聖經》

5. 編程學習網站推薦

網站 網址
菜鳥教程
W3School
實驗樓
猿學
慕課網
SegmentFault
博客園
GitHub
掘金
學習數據科學
易百教程
看雲

三、總結

通篇寫完,感覺自己也重新學到了很多,學習就是一個反覆複習的過程,每次學習都能帶給自己不一樣的收穫。希望以上內容可以給初入計算機相關專業的萌新帶來一些幫助,後面我會不斷更新和優化本文,請大家持續關注。

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

【其他文章推薦】

※想知道網站建置網站改版該如何進行嗎?將由專業工程師為您規劃客製化網頁設計後台網頁設計

※不管是台北網頁設計公司台中網頁設計公司,全省皆有專員為您服務

※Google地圖已可更新顯示潭子電動車充電站設置地點!!

※帶您來看台北網站建置台北網頁設計,各種案例分享

做程序員的一些偏見

“人類的心靈有一種神奇的能力,它能夠感知到別人的虛情假意。如果銷售人員的暗示是一種虛情假意的產物,那麼幾乎刻意肯定的是,這種暗示在客戶心中產生的結果也不會是一種真實的情感。”

                                                                ——諾瓦爾·霍金斯

前天,銷售同事老吳還說,做銷售一定要講人品,而且做人很重要。我很贊同他的觀點,但我還是對他的觀點做了補充:不單單是銷售要學會做人,我們任何一個崗位、任何一個人都要學會如何做人。崗位是做事層面,做人是做事的根基,無論你是銷售還是程序員、都離不開做人。我在部門裡經常對同事們說,甚至在面試的時候也跟應聘者強調,我們都是全民銷售。因為我們扁平化的開放管理制度,我們任何一個員工都有可能直接面對客戶。作為服務行業的我們,任何一個同事的印象以及專業態度都是我們的招牌。面對客戶就是面對市場,面對市場的員工就是覆蓋了銷售的角色。我們每個人都代表着一個企業,更代表了自己。有些客戶可能因為我們需求做得好,所以給了我更多的機會;也有可能有些客戶因為我們的美工同事洞悉到了客戶的需求而用真誠的設計打動了客戶,贏下了訂單;甚至可能是我們善良、踏實、勤奮的程序員同事感動了客戶,非要跟我們合作不可。這裏都包含着公司的文化和個人的修養。

 

我過去一直深受着各種流言的毒害,當然,我不會把問題丟給環境,真正的問題在於自己沒有足夠的獨立思考和判斷能力。別人說程序員普遍悶騷,別人說美工都很藝術,還有人說需求就是要有足夠的健談和洞察能力。其實,話有時候並沒有毛病,但我們缺少一個宏觀與高度的視野能力會很容易讓自己“入戲”,也就是會以偏概全。就像同事老吳說銷售考驗做人,如果我弱一點,我真會以為作為程序員的自己就沒那麼需要關注做人層面了,反正自己不用天天面對客戶。這就是我們常說的短見。

 

我現在的職位寫着是部門經理,不止戰略,在戰術上如架構、設計、開發我都一直在做,還帶着近80號人。我目前的狀態不是因為我踩正了職業規劃路線,或者我有管理的能力。而是我看不過眼和忍受不了之前團隊的低效和散漫,想自己做得有成就一點,有效率一點而已。沒人敢這麼做,而領導敢給我這樣一個機會,那就只有我自己扛起大旗向前沖了。有時候,當自己真覺得環境待不下去了,可能就是自己的機會。我不知道自己有沒有這個能力,但我有一個看清問題本質的視野和敢說敢做勇氣。個人發展的本質並不是職位驅動的,任何一個有能力的人都能有機會上升,不管你是美工、測試、需求還是程序員,就看自己願不願意放開自己思維和勇氣。我很早就已經說過,職位在做事面前都是一文不值。千萬不要被各種所謂的管理晉陞路線和技術大咖晉陞路線給誤導。人生都是問題驅動的,每個人的起點都不一樣,問題也都不一樣。多把視野放在當前問題身上,而不是帶着別人給出的規劃建議去逃避自己當前的問題,這個同事不好,那個老闆不行,這都不是自己想要的,這都是借口。能讓自己過得好,能讓家人過得好才是王道。所以,從這個角度看,無論什麼職位,跑得越高,越是辛苦。認識不了這個本質的,永遠做不了高層。

 

我們一出生就已經內置了銷售這個職位,我們需要與人打交道,我們需要結交朋友,我們需要面試找工作等等。其實,我們無時無刻在銷售着自己。而真誠就是我們每一個都需要具備的銷售品質。做銷售的門檻很低,可是考驗很大,但前途也無可限量。

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

【其他文章推薦】

※想知道網站建置網站改版該如何進行嗎?將由專業工程師為您規劃客製化網頁設計後台網頁設計

※不管是台北網頁設計公司台中網頁設計公司,全省皆有專員為您服務

※Google地圖已可更新顯示潭子電動車充電站設置地點!!

※帶您來看台北網站建置台北網頁設計,各種案例分享

法國通過反浪費法 禁丟棄未售出商品

2020年2月3日苦勞網報導;陳韋綸編譯

繼禁止超商丟棄未售出食物後,,禁止服飾與精品公司摧毀未售出的商品,不過卻被批評缺乏罰則而難有成效。

共130項條文的《反浪費與經濟流通法案》,要求製造、進口與批發商,其中也包括亞馬遜(Amazon)等線上零售商,捐贈未出售的貨物,商品範圍涵蓋電子產品、衛生用品與化妝品。此外,該法案也希望2025年前回收所有塑膠製品,並將一次性塑膠瓶的使用減少一半。速食餐廳則須在2023年前停止使用塑膠容器。

總理菲力普(Édouard Philippe)表示,在法國,每年未使用卻被丟棄的消費產品高達6億5千萬歐元(約新台幣217億元)。根據「污染者付費」原則,企業也須為自己製造的廢棄物付費,例如菸草製造商必須在隔年支付處理煙蒂的費用。

在法國,。當初推動立法要求超商捐贈過期食物的德朗巴斯(Arash Derambarsh)表示,新法雖然立意良善,但是缺乏誠意,「如果沒有罰則,人們只會忽略法律」,導致新法難有成效。

※轉載自()

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

【其他文章推薦】

USB CONNECTOR掌控什麼技術要點? 帶您認識其相關發展及效能

※評比前十大台北網頁設計台北網站設計公司知名案例作品心得分享

※智慧手機時代的來臨,RWD網頁設計已成為網頁設計推薦首選

※評比南投搬家公司費用收費行情懶人包大公開

世界最大廢水養殖系統在印度 濕地淨化勝過污水處理廠 仍不敵政府開發

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

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

【其他文章推薦】

※想知道網站建置網站改版該如何進行嗎?將由專業工程師為您規劃客製化網頁設計後台網頁設計

※不管是台北網頁設計公司台中網頁設計公司,全省皆有專員為您服務

※Google地圖已可更新顯示潭子電動車充電站設置地點!!

※帶您來看台北網站建置台北網頁設計,各種案例分享

Python字典 你必須知道的用法系列

本文Python版本為3.7.X,閱讀本文之前需了解python字典的基本用法。

介紹

字典(dict)是Python中內置的一個數據結構,由多個鍵值對組成,鍵(key)和值(value)用冒號分隔,每個鍵值對之間用逗號(,)分隔,整個字典包括在大括號中({}),鍵必須是唯一的,值可以取任何類型,但是鍵必須是不可變類型,如字符串,数字或元組。

底層使用了hash表來關聯key和value,dict是無序的。特點包括:

  1. 查找和插入的速度極快,不會隨着key的增加而變慢;
  2. 需要佔用的內存較多

所以,dict是一種以空間換取時間的數據結構,應用於需要快速查找的場景。

操作

常用方法

get()

返回指定鍵的值,如果key不存在,則返回默認值(默認為None),而不會報錯,語法為dict.get(key)。

dict_1['age'] = 24

In [7]: print(dict_1.get('age'))
24

In [11]: print(dict_1.get('nama'))
None

In [12]: print(dict_1['nama'])
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
<ipython-input-12-ef61a380920e> in <module>
----> 1 print(dict_1['nama'])

KeyError: 'nama'

key in dict

使用in操作符來判斷鍵是否存在於字典中,存在則返回True,否則返回False,語法為:key in dict。

In [15]: dict_1
Out[15]: {'name': None, 'age': 24, 'sex': None}

In [16]: print('name' in dict_1)
True

In [17]: print('nama' in dict_1)
False

在python 2中該功能使用has_key()方法實現。

items()

以列表形式返回可遍歷的(鍵, 值)元組數組,語法為dict.items()。

In [18]: dict_1
Out[18]: {'name': None, 'age': 24, 'sex': None}

In [19]: print(dict_1.items())
dict_items([('name', None), ('age', 24), ('sex', None)])

In [20]: for key, value in dict_1.items():
    ...:     print(key, value)
    ...:
name None
age 24
sex None

keys()

以列表返回一個字典的所有鍵:dict.keys()

In [21]: dict_1
Out[21]: {'name': None, 'age': 24, 'sex': None}

In [22]: print(dict_1.keys())
dict_keys(['name', 'age', 'sex'])

values()

以列表形式返回字典中的所有值:dict.values()

In [27]: dict_1
Out[27]: {'name': None, 'age': 24, 'sex': None, 'sub_name': 'Tony'}

In [28]: print(dict_1.values())
dict_values([None, 24, None, 'Tony'])

setdefault()

和get()類似,用戶獲得與給頂尖相關聯的值,不同的是,該方法如果鍵不存在時會添加鍵並將值設為默認值,語法為:dict.setdefault(key, default=None)。

In [23]: dict_1
Out[23]: {'name': None, 'age': 24, 'sex': None}

In [24]: print(dict_1.setdefault('name'))
None

In [25]: print(dict_1.setdefault('name', 'Tony'))
None

In [26]: print(dict_1.setdefault('sub_name', 'Tony'))
Tony

In [27]: dict_1
Out[27]: {'name': None, 'age': 24, 'sex': None, 'sub_name': 'Tony'}

update()

語法為:dict_1.update(dict_2),用於把dict_2的鍵值對更新到dict_1中,如果有相同的鍵會被覆蓋。

In [31]: dict_1
Out[31]: {'name': None, 'age': 24, 'sex': None, 'sub_name': 'Tony'}

In [32]: dict_2
Out[32]: {'name': 'Mary', 'age': 18, 'sex': None, 'sub_name': ''}

In [33]: dict_1.update(dict_2)

In [34]: dict_1
Out[34]: {'name': 'Mary', 'age': 18, 'sex': None, 'sub_name': ''}

clear()

刪除字典中的所有項,dict.clear(),舉個例子:

In [1]: dict_1 = dict(name="Tony", age=24)

In [2]: dict_2 = dict_1

In [3]: print(dict_2)
{'name': 'Tony', 'age': 24}

In [4]: dict_2.clear()

In [5]: dict_2
Out[5]: {}

In [6]: dict_1
Out[6]: {}

copy()

淺拷貝原始字典,返回一個具有相同鍵值對的新字典,dict.copy(),舉個例子:

In [1]: dict_1 = dict(name='Tony', info=['boy', 24])

In [2]: dict_3 = dict_1.copy()

In [3]: dict_3['name'] = "Ring"

In [4]: dict_3['info'].remove('boy')

In [5]: dict_3
Out[5]: {'name': 'Ring', 'info': [24]}

In [6]: dict_1
Out[6]: {'name': 'Tony', 'info': [24]}

fromkeys()

創建一個新字典,dict.fromkeys(seq[, value]),以序列seq中的元素做字典的鍵,value為字典所有鍵對應的初始值,其中value為可選參數, 默認為None。適用於數據初始化,舉個例子:

In [1]: info = ['name', 'age', 'sex']

In [2]: dict_1 = dict.fromkeys(info)

In [3]: dict_1
Out[3]: {'name': None, 'age': None, 'sex': None}

常見操作

合併字典

有四種方式:

  1. 常規處理
In [15]: dict_1
Out[15]: {'Tony': 24}

In [16]: dict_2
Out[16]: {'ben': 18}

In [17]: dict3 = dict()

In [18]: for key, value in dict_1.items():
    ...:     dict_3[key] = value
    ...:

In [19]: for key, value in dict_2.items():
    ...:     dict_3[key] = value
    ...:

In [20]: dict_3
Out[20]: {'Tony': 24, 'ben': 18}
  1. update()
In [9]: dict_1
Out[9]: {'Tony': 24}

In [10]: dict_2
Out[10]: {'ben': 18}

In [12]: dict_3 = dict_1.copy()

In [13]: dict_3.update(dict_2)

In [14]: dict_3
Out[14]: {'Tony': 24, 'ben': 18}
  1. 藉助字典的dict(d1, **d2)方法
In [33]: dict_1
Out[33]: {'Tony': 24}

In [34]: dict_2
Out[34]: {'ben': 18}

In [35]: dict_3 = dict(dict_1, **dict_2)

In [36]: dict_3
Out[36]: {'Tony': 24, 'ben': 18}

進階

字典推導式

和列表推導式類似,優點是底層用C實現,會快很多,推薦使用。

對換字典的鍵值

使用字典推導式可以輕鬆對換一個字典的鍵值:

In [42]: dict_4
Out[42]: {24: 'Tony', 18: 'ben'}

In [43]: dict_3
Out[43]: {'Tony': 24, 'ben': 18}

In [44]: dict_4 = {k:v for v, k in dict_3.items()}

In [45]: dict_4
Out[45]: {24: 'Tony', 18: 'ben'}

從字典中提取子集

想創建一個字典,其本身是另一個字典的子集。

舉個例子:

In [88]: a = {'Ben': 18, 'Jack': 12, 'Ring': 23, 'Tony': 24}

In [89]: b = {k:v for k, v in a.items() if v > 18}

In [90]: b
Out[90]: {'Ring': 23, 'Tony': 24}

生成有序字典

在Python3.6之前的字典是無序的,但是有時候我們需要保持字典的有序性,orderDict可以在dict的基礎上實現字典的有序性,這裏的有序指的是按照字典key插入的順序來排列,這樣就實現了一個先進先出的dict,當容量超出限制時,先刪除最早添加的key。
舉例:

In [49]: from collections import OrderedDict

In [50]: ordered_dict = OrderedDict([('a', 2), ('b', 4), ('c', 5)])

In [51]: for key, value in ordered_dict.items():
    ...:     print(key, value)
    ...:
a 2
b 4
c 5

可以看到OrderedDict是按照字典創建時的插入順序來排序。

原理:OrderedDict內部維護了一個雙向鏈表,它會根據元素加入的順序來排列鍵的位置,這也就導致OrderedDict的大小是普通字典的2倍多。

合併列表中key相同的字典

也就是生成所謂的一鍵多值字典,需要將對應的多個值保存在其它容器比如列表或集合,取決於多值是否需要保證唯一性。

舉個例子:

In [64]: from collections import defaultdict

In [65]: a = [{'a': 1}, {'b': 3}, {'c': 4}, {'a':5}, {'b':2}, {'b': 4}]

In [66]: b = defaultdict(list)

In [67]: [b[k].append(v) for item in a for k, v in item.items()]
Out[67]: [None, None, None, None, None, None]

In [68]: b
Out[68]: defaultdict(list, {'a': [1, 5], 'b': [3, 2, 4], 'c': [4]})

In [69]: b['a']
Out[69]: [1, 5]

尋找兩個字典的異同

場景:尋找兩個字典中的異同,包括相同的鍵或者相同的值。

分析:字典是一系列鍵值之間的映射集合,有以下特點:

  1. keys()會返回字典中的所有鍵,並且字典的鍵是支持集合操作的,所以利用集合的交叉並補即可對字典的鍵進行處理;
  2. items()返回(key, value)組成的對象,支持集合操作;
  3. values()並不支持集合操作,因為並不能保證所有的值是唯一的,但是如果必須要判斷操作,可以先將值轉化為集合來實現。

舉例:

In [78]: a = {'a':1, 'b':2, 'c':3}

In [79]: b = {'b':3, 'c':3, 'd':4}

In [80]: a.keys() & b.keys()
Out[80]: {'b', 'c'}

In [81]: a.keys() - b.keys()
Out[81]: {'a'}

In [82]: a.items() & b.items()
Out[82]: {('c', 3)}

再舉一個例子,在創建一個字典時,期望可以去除某些鍵:

In [85]: a
Out[85]: {'a': 1, 'b': 2, 'c': 3}

In [86]: c = {k: a[key] for k in a.keys() - {'b'}}

In [87]: c
Out[87]: {'a': 3, 'c': 3}

以上。

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

【其他文章推薦】

※想知道網站建置網站改版該如何進行嗎?將由專業工程師為您規劃客製化網頁設計後台網頁設計

※不管是台北網頁設計公司台中網頁設計公司,全省皆有專員為您服務

※Google地圖已可更新顯示潭子電動車充電站設置地點!!

※帶您來看台北網站建置台北網頁設計,各種案例分享

王傳福:到2030年私家車將全面電動化

近日,第二屆中國電動汽車百人會論壇在京召開。比亞迪股份有限公司董事長王傳福在本屆大會上指出:國家政策對新能源車發展具有巨大推動作用。在這體種體制優勢的推動下,到2020年大巴和計程車將全面電動化,到2025年,貨車(物流車)全面電動化,到2030年私家車將全面電動化。

縱觀全球新能源車市場,歐洲新能源車在2015年有所增長,美國則因為油價下降導致新能源車增速放緩,而中國則是增長最為迅速的新能源車市場。“可以看出兩種機制下增長的態勢,中國是體制在推動,國外是市場資源的配製在推動,兩個手造成的結果是完全不一樣的。中國新能源汽車市場產銷快速增長,最後的推手凸顯了政府的體制優勢。”王傳福表示。

王傳福稱,我國體制機制的優勢在於強有力的政策支持。一個標誌性事件就是2013年7月份國務院頒佈了新能源汽車發展指導意見,後來被人們稱為“三十條”。王傳福認為,“三十條”是全球最系統、最科學、最全面、最有效的政策體系,囊括了財稅、政策、法規、標準、基礎設施等一系列政策。“三十條”已經逐項落實,帶來了如今新能源車市場飛速發展的現狀。

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

【其他文章推薦】

※想知道網站建置網站改版該如何進行嗎?將由專業工程師為您規劃客製化網頁設計後台網頁設計

※不管是台北網頁設計公司台中網頁設計公司,全省皆有專員為您服務

※Google地圖已可更新顯示潭子電動車充電站設置地點!!

※帶您來看台北網站建置台北網頁設計,各種案例分享

常隆客車和AESC公司達成了電動客車錳酸鋰離子電池供應協定

2016年1月14日, 江蘇常隆客車有限公司(江蘇省江陰市)和AESC公司(神奈川縣座間市)達成了電動客車錳酸鋰離子電池供應協定,雙方高層出席了隆重的簽字儀式。本次合作協定初期電池供給規模為30MWh,可以滿足100台12米電動客車的錳酸鋰電池。雙方還預計到2017年可以持續供貨900MWh規模的錳酸鋰電池,滿足3000輛純電動客車生產需求。

通過雙方合作,常隆電動客車將更加安全可靠、經久耐用,努力為市場提供最好的電動客車、最優質的服務、最值得信賴的品牌。同時雙方約定今後持續探討本次合作的動力電池在儲能領域應用的可行性。雙方計畫同步開拓中國市場和國際市場。

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

【其他文章推薦】

※想知道網站建置網站改版該如何進行嗎?將由專業工程師為您規劃客製化網頁設計後台網頁設計

※不管是台北網頁設計公司台中網頁設計公司,全省皆有專員為您服務

※Google地圖已可更新顯示潭子電動車充電站設置地點!!

※帶您來看台北網站建置台北網頁設計,各種案例分享

MySQL InnoDB 事務

MySQL 原理篇

MySQL5.5 及以後版本的默認存儲引擎使用的是 InnoDB,接下來針對事務的講解都是基於 InnoDB 存儲引擎的。

事務的定義

事務:數據庫操作的最小工作單元,是作為單個邏輯工作單元執行的一系列操作; 事務是一組不可再分割的操作集合(工作邏輯單元)。

典型事務使用場景:轉賬

update user_account set balance = balance - 1000 where userID = 3;
update user_account set balance = balance + 1000 where userID = 1;

MySQL 開啟事務

/*
  BEGIN / START TRANSACTION        --手工
  COMMIT / ROLLBACK                --事務提交或回滾
  SET SESSION autocommit = ON/OFF  --設定會話級別事務是否自動開啟
*/

MySQL 默認是開啟事務的,通過 SHOW VARIABLES like 'autocommit'; 可以查看 MySQL 的事務開啟情況。

  • 在 autocommit = ON(自動提交事務)的情況下,可以執行 BEGIN; 或者 START TRANSACTION; 命令,改為手動提交事務,執行完 SQL 語句后,需要通過 COMMIT 命令提交事務,或者通過 ROLLBACK 命令回滾事務。
  • 在 autocommit = OFF(手動提交事務)的情況下,執行完 SQL 語句后,需要通過 COMMIT 命令提交事務,或者通過 ROLLBACK 命令回滾事務。

JDBC 編程

connection.setAutoCommit(boolean);

測試命令

SHOW VARIABLES like 'autocommit';

/* autocommit為ON */
update teacher set name ='seven' where id =1;
insert teacher (name,age) value ('james',22);
delete from teacher where name = 'james';

/* autocommit為ON如何開啟事務 */
BEGIN;
START TRANSACTION;

update teacher set name ='seven' where id =1;
insert teacher (name,age) value ('james',22);
delete from teacher where name = 'james';

COMMIT;
ROLLBACK;

/* 將autocommit改成OFF */
set session autocommit = OFF;
update teacher set name ='seven' where id =1;
insert teacher (name,age) value ('james',22);
delete from teacher where name = 'james';

COMMIT;
ROLLBACK;

事務 ACID 特性

原子性(Atomicity):最小的工作單元,整個工作單元要麼一起提交成功,要麼全部失敗回滾。

一致性(Consistency):事務中操作的數據及狀態改變是一致的,即寫入資料的結果必須完全符合預設的規則,不會因為出現系統意外等原因導致狀態的不一致。

隔離型(Isolation):一個事務所操作的數據在提交之前,對其他事務的可見性設定(一般設定為不可見)。

持久性(Durability):事務所做的修改就會永久保存,不會因為系統意外導致數據的丟失。

參考()這篇博文,講了一下原子性和一致性的區別。

事務併發帶來了哪些問題

臟讀

比如 user 表中有一條用戶數據,執行了如下操作:

  1. 事務B更新 id=1 的數據,age 更新為18,不提交事務
  2. 事務A查詢 id=1 的數據
  3. 事務B回滾剛才的更新操作

這個時候,事務A中查詢出的 id=1 的數據,age 的值是16還是18?

不可重複讀

 

比如 user 表中有一條用戶數據,執行了如下操作:

  1. 事務A查詢 id=1 的數據
  2. 事務B更新 id=1 的數據,age 更新為18,並提交事務
  3. 事務A再次查詢 id=1 的數據

這個時候,事務A兩次查詢出的 id=1 的數據,age 的值是16還是18?

幻讀

比如在 user 表中執行了如下操作:

  1. 事務A查詢 age>15 的數據
  2. 事務B新增一條數據,age=22,並提交事務
  3. 事務A再次查詢 age>15 的數據

這個時候,事務A兩次查詢出的數據,數量是1條還是2條?

事務四種隔離級別

SQL92 ANSI/ISO標準:http://www.contrib.andrew.cmu.edu/~shadow/sql/sql1992.txt

Read Uncommitted(未提交讀未解決併發問題

事務未提交對其他事務也是可見的,臟讀(dirty read)

Read Committed(提交讀)解決臟讀問題

一個事務開始之後,只能看到自己提交的事務所做的修改,不可重複讀(non repeatable read)

Repeatable Read(可重複讀解決不可重複讀問題

在同一個事務中多次讀取同樣的數據結果是一樣的,這種隔離級別未定義解決幻讀的問題

Serializable(串行化)解決所有問題

最高的隔離級別,通過強制事務的串行執行

InnoDB 引擎對隔離級別的支持程度

事務隔離級別

臟讀

不可重複讀

幻讀

未提交讀(Read Uncommitted)

可能

可能

可能

已提交讀(Read Committed)

不可能

可能

可能

可重複讀(Repeatable Read)

不可能

不可能

對 InnoDB 不可能

串行化(Serializable)

不可能

不可能

不可能

事務隔離級別的併發能力:未提交讀 > 已提交讀 > 可重複讀 > 串行化

InnDB 引擎默認的事務隔離級別是可重複讀(Repeatable Read),在該級別中它把幻讀的問題也解決了。InnDB 中事務隔離級別通過鎖、MVCC 實現。

通過如下語句查看 InnoDB 的默認事務隔離級別:

/* 全局、當前會話的隔離級別 */
SELECT @@global.tx_isolation, @@tx_isolation;

通過如下語句設置 InnoDB 的事務隔離級別:

/* 設置全局隔離級別 */
set global transaction isolation level read committed;
/* 設置當前會話的隔離級別 */
set session transaction isolation level read committed;

接下來我們來測試一下 InnoDB 的默認事務隔離級別(Repeatable Read)是否解決了臟讀、不可重複讀、幻讀的問題。

數據準備:

CREATE TABLE `user` (
  `id` int(11) NOT NULL,
  `name` varchar(32) NOT NULL,
  `age` int(11) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

insert into `user` (`id`, `name`, `age`) values('1','Ada','16');

是否解決了臟讀的問題?

開啟兩個 MySQL 客戶端,模擬事務A和事務B的操作,執行步驟如下:

  1. 事務B開啟手動事務,更新 id=1 的數據,age 更新為18,不提交事務
  2. 事務A查詢 id=1 的數據
  3. 事務B回滾剛才的更新操作

圖中的数字是執行步驟,通過下圖可以看出事務A的執行結果是16,InnDB 的默認事務隔離級別完美的解決了臟讀的問題。

是否解決了不可重複讀的問題?

開啟兩個 MySQL 客戶端,模擬事務A和事務B的操作,執行步驟如下:

  1. 事務A開啟手動事務,查詢 id=1 的數據
  2. 事務B更新 id=1 的數據,age 更新為18,並提交事務
  3. 事務A再次查詢 id=1 的數據

圖中的数字是執行步驟,通過下圖可以看出事務A兩次的執行結果都是16,沒有受事務B更新操作的影響,InnDB 的默認事務隔離級別完美的解決了不可重複讀的問題。

是否解決了幻讀的問題?

開啟兩個 MySQL 客戶端,模擬事務A和事務B的操作,執行步驟如下:

  1. 事務A開啟手動事務,查詢 age>15 的數據
  2. 事務B新增一條數據,age=22,並提交事務
  3. 事務A再次查詢 age>15 的數據

圖中的数字是執行步驟,通過下圖可以看出事務A兩次的執行結果都是一條數據,沒有受事務B新增操作的影響,InnDB 的默認事務隔離級別完美的解決了幻讀的問題。

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

【其他文章推薦】

※想知道網站建置網站改版該如何進行嗎?將由專業工程師為您規劃客製化網頁設計後台網頁設計

※不管是台北網頁設計公司台中網頁設計公司,全省皆有專員為您服務

※Google地圖已可更新顯示潭子電動車充電站設置地點!!

※帶您來看台北網站建置台北網頁設計,各種案例分享