月份: 2020 年 5 月

  • 特斯拉:把電動汽車裡的電賣回給電網未來或可實現

    近日,特斯拉中國公共策劃與充電基礎設施總監高翔在接受記者採訪時表示,“充電並不是一件很難的事情“,甚至以後可以“把電賣給電網“。

    電動汽車充電並不難

    目前,對比汽油車加油,電動車充電仍然給人們一種“充電還是很困難“的感覺。高翔對此解釋道,汽油車發展超過100年了,剛開始也是很困難,但是現在到處都有加油站,我們也覺得很方便。而事實上,充電並沒有我們想像中那麼難,舉例來說,電動車充電並不需要像加油站那樣大的土地,也不需要擔憂運輸、儲油的安全性問題。

    據悉,目前特斯拉汽車的充電方式有三種:一是家庭充電,充電設備隨車贈送;二是建在各大商場、酒店、旅遊地的“目的地充電樁”,方便車主外出時充電。跟家電充電一樣,目的地充電樁同樣是支援220V電壓,所以充電時間較長,充滿一次需要11.5-13小時左右;三是超級充電站。由於其配備的超級充電器是通過特製電纜繞過車載充電設備,直接將380V的直流電輸入電池,所以充電時間大為縮短。目的地充電樁每充電1小時可行駛至少50公里,而使用超級充電站,20分鐘就能充滿一半,80分鐘即可完全充滿,並可行駛400公里以上。並且車主在此可以免費充電。

    電動車發展明年將會進入爆發式增長

    為什麼大家對發展電動汽車有很深的理解,一個是霧霾,近幾年日益嚴重;另外一個是能源危機,我們採用的化石能源60%左右依賴於進口。在能源危機和環境壓力面前,我們需要很好的解決方案。而在出行方式裡面,汽油車占到90%的汽油消耗量,所以電動汽車對這方面有很大的幫助。

    同時,國家新的標準馬上也要發佈,高翔預測,整個電動車行業到2016年將會進入一個爆發式增長,甚至在以後,國家除了對車進行補貼外,也將會對基礎設施進行支持,大力推進基礎設施充電的發展。有了這些,剩下的就是企業把車做好。未來充電市場和電動車行業一定是相輔相成的。

    把車裡的電賣給電網

    電動汽車行業與電網本來就是天然的合作關係。電動汽車除了把電能作為能源之外,其實也是能源互聯網以及智慧電網中的一個環節。據高翔介紹,電網作為一個承擔著中國電力行業社會責任的企業,對於電動汽車的發展一直都是支援的,特別是北上廣深等大城市,在這方面有著非常清晰的政策。

    而從長遠來看,電動汽車的發展對電網來說也是一個好事。充電設施多了,對電網企業了來說,最重要的絕不是“充個電、收個服務費“,而是未來發展智慧電網、甚至是發展車和電網的互聯互通。比如說VTOG(雙向逆變充放電技術),從車反過來給電網充電,充好電的車相當於無數個儲能電池,對電網起到削峰填穀的作用,也就是說,晚上用不掉的電儲存到車裡來,白天用電高峰時候電動汽車用戶再把這些電散落地賣還給電網。

    高翔解釋道,現在電網發電還做不到即時的調控,要滿足高峰用電,就需要按照需求最大值來發電,但是電網大多數時間是用不了這麼多電的,晚上好多電用不掉但是也不能停,否則經濟損失很大。如果採取了上面這種做法的話,不但車主能得到收益,電網也能節省很大的發電及儲能成本,將是一個非常理想的削峰填穀模式。

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

    【其他文章推薦】

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

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

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

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

  • Uber響應環保 在中國大陸推出「電動車日」

    中國大陸霧霾嚴重,交通工具被視為兇手之一,故中央政府已開始推出電動車推廣政策,希望能減輕霾害問題。線上叫車業者Uber響應減碳,首度在北京、上海、廣州、成都等中國大陸的13個城市啟動「電動車日」,只要駕駛開電動車載客,就能享受額外獎勵。

    中國Uber表示,「電動車日」的活動是為了響應環保減碳而推出。叫車用戶可透過Uber叫車平台呼叫特斯拉、北汽新能源等電動車,或者豐田Corolla Hybrid或Levin等油電混和車。此外,在今年底前以電動車車款加入共乘的車主將可享有額外獎勵,將能鼓勵中國大陸民眾購置電動車。

    據統計,Uber上海平台上已有30%的車主駕駛電動車,Uber未來也將與更多電動車品牌合作,透過共乘與綠能發展計畫推廣環保。

    根據中新財經網報導,目前中國大陸汽車數量已達2.76億輛,所排放的廢氣對霾害影響甚大。若能以電動車取代燃油車,對於霾害會有正面幫助。中國大陸官方已陸續在各地推出電動公車,並祭出電動車補助措施以及產業補貼,希望能增加民眾採用電動車的比例。

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

    【其他文章推薦】

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

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

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

    南投搬家前需注意的眉眉角角,別等搬了再說!

  • 這是下一個 Tesla!新創公司 Faraday 宣布 10 億美元電動車投資計畫

    這是下一個 Tesla!新創公司 Faraday 宣布 10 億美元電動車投資計畫

    近日一家在洛杉磯成立的新創公司 Faraday Future 引發了巨大關注,號稱投資 10 億美元建設電動車製造廠,據該公司官網顯示 4 位副總裁來自 Tesla,團隊規模大約為 400 人,這一投資規模在整個電動車產業來看,都不是一筆小數目。

    Faraday Future 的總部位於洛杉磯南部,相比於一般新創公司而言,Faraday Future 的團隊規模比較大,目前已經擁有了 400 名員工,這家專注於電動車市場的新創公司並沒有在業內引發太多關注。最近華爾街日報報導該公司宣布投資 10 億美元建廠,這一筆投資使得 Faraday 聲名大振。   據該公司的網站資訊顯示,Faraday Future 將以使用者為中心,把一流的技術引入電動車設計、致力於連結使用者的駕駛體驗和生活。4 位副總裁均來自電動車製造商 Tesla,Tesla Model S 製造業務總監 Dag Reckhorn 擔任製造業務副總裁,Tesla 前人力資源總監 Alan Cherry 擔任 Faraday 的人力資源副總裁,Tesla 前採購總監 Tom Wessner 擔任 Faraday 供應鏈管理副總裁。但未公開 CEO 的資訊,據加州政府提供的 Faraday Future 註冊資訊顯示,該公司的 CEO 與中國網路公司樂視有密切關係,出任 CEO 的正是樂視 CEO 的助理,樂視在 2015 年上半年發表了超級汽車計畫。  

      Faraday 研發副總裁、Tesla 前總監 Nick Sampson 表示,市面上的汽車已經不能滿足用戶的需求,Faraday 將提供最智慧化的電動車,幫助用戶與外部世界連接,這位高階主管拒絕公開 Faraday 的投資方。Nick Sampson 於 2012 年 1 月從 Tesla 離職,對於他的離職,Tesla CEO Elon Musk 曾公開表示是他勸 Nick Sampson 離職的,因為 Tesla 沒有適合他的職位。   從團隊構成到產品戰略,這家神秘新創公司直指 Tesla,在公司的名稱上也與 Tesla 有異曲同工之妙,Tesla 的名字來自於交流電發明者 Nikola Tesla,而 Faraday 的名字則是來自電磁感應的發現者 Michael Faraday。

    (本文授權轉載自《》─〈〉)

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

    【其他文章推薦】

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

    網頁設計一頭霧水??該從何著手呢? 找到專業技術的網頁設計公司,幫您輕鬆架站!

    ※想知道最厲害的台北網頁設計公司推薦台中網頁設計公司推薦專業設計師”嚨底家”!!

  • 利用爬蟲爬取LOL官網上皮膚圖片

    利用爬蟲爬取LOL官網上皮膚圖片

      今天在瀏覽網頁時,看到一篇很有意思的文章,關於網絡爬蟲的。該文章是講述如何利用request爬取英雄聯盟官網皮膚圖片。看過文章后覺得挺有用的,把代碼拿過來運行了一下,果真爬取成功。下面給大家分享一下代碼。

      首先得利用cmd命令指示符安裝requests庫,json,re,time。

      安裝完成后,第一步是獲取英雄ID從而為先面判決URL作準備。

    def getLOLImages():
        header = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.62 Safari/537.36'}
        url_js = 'http://lol.qq.com/biz/hero/champion.js'
        #獲取JS源代碼 Str bytes
        res_js = requests.get(url_js).content
        #轉碼 轉成字符串
        html_js = res_js.decode()
        #正則表達式
        req = '"keys":(.*?),"data"'
        list_js = re.findall(req,html_js)
        #轉成dict
        dict_js = json.loads(list_js[0])
        # print(type(dict_js))
        #定義圖片列表
        pic_list = []
        for key in dict_js:
            # print(key)#英雄ID

    第二步就是拼接URL了,通過發現英雄皮膚url的取名方式,我們可以方向最後的数字是不同的。讓后通過此方法來獲取圖片地址。

    for i in range(20):
        number = str(i)
        if len(number) == 1:
            hero_num = "00"+number
        elif len(number) == 2:
            hero_num = "0"+number
        numstr = key+hero_num
        url = "http://ossweb-img.qq.com/images/lol/web201310/skin/big"+numstr+".jpg"
        #http://ossweb-img.qq.com/images/lol/web201310/skin/big81000.jpg
        pic_list.append(url)

    第三步是獲取圖片名稱,path那行是放置圖片的地址,注意結尾的\\不能丟。

    list_filepath = []
        path = "D:\Pycharmdaima\Pachong\LOLTU\\"
    for name in dict_js.values():
        for i in range(20):
            file_path = path+name+str(i)+'.jpg'
            list_filepath.append(file_path)

    第四步就是下載圖片了。

    n = 0
    for picurl in pic_list:
        res = requests.get(picurl)
        n += 1
        #獲取狀態碼
        if res.status_code == 200:
            print("正在下載%s"%list_filepath[n])
            time.sleep(1)
            with open(list_filepath[n],'wb') as f:
                f.write(res.content)

    最後,調用一下getLOLImages()方法

    getLOLImages()

      注意,我第一次用了源碼,後來發現運行太慢,檢查一下源碼后發現代碼末尾調用了一個time.sleep()方法。這樣是為了限制爬取速度,避免速度過快被網站發現而中斷。經過調試,我中途暫停代碼運行,將sleep()方法註釋掉,爬取速度果然加快,而且沒有中斷。

      下面是我的爬取成果:

     

     

    本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理
    【其他文章推薦】

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

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

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

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

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

  • .NET進階篇06-async異步、thread多線程2

    .NET進階篇06-async異步、thread多線程2

    知識需要不斷積累、總結和沉澱,思考和寫作是成長的催化劑

    內容目錄

    一、線程Thread

    .NET中線程操作封裝為了Thread類,可以讓開發者對線程進行直觀操作。Thread提供了實例方法用於管理線程的生命周期和靜態方法用於控制線程的一些訪問存儲等一些外在的屬性,相當於工作空間環境變量了

    1、生命周期

    線程的生命周期有創建、啟動、可能掛起、等待、恢復、異常、然後結束。用Thread類可以容易控制一個線程的全生命周期

    Thread類的構造函數重載可以接受ThreadStart無參數和ParameterizedThreadStart有參數的委託,然後調用實例的Start()方法啟動線程。Thread的構造函數的帶有參數的委託,參數是一個object類型,因為我們可以傳入任何信息

    Thread t1 = new Thread(() => {
        Console.WriteLine($"新線程  {Thread.CurrentThread.ManagedThreadId.ToString("00")}");
    });
    t1.Start();
    Thread t2 = new Thread((obj) => {
        Console.WriteLine($"新線程  {Thread.CurrentThread.ManagedThreadId.ToString("00")},參數 {obj.ToString()}");
    });
    t2.Start("hello kitty");

    線程啟動后,可以調用線程的Suspend()掛起線程,線程就會處於休眠狀態(不繼續執行線程內代碼),調用Resume()喚醒線程,還有一個不太建議使用的Abort()通過拋出異常的方式來銷毀線程,隨後線程的狀態就會變為AbortRequested

    常用的還有線程的等待,在主線程上啟用工作線程后,有時需要等待工作線程的完成后,主線程才繼續工作。可以調用實例方法Join(),當然我們可以傳入時間參數來表明我主線程最多等你多久

    2、後台線程

    上一章我們知道Thread默認創建的是前台線程,前台線程會阻止系統進程的退出,就是啟動之後一定要完成任務的後台線程會伴隨着進程的退出而退出。通過設置屬性IsBackground=true改為後台線程。另外還可以通過設置Priority指定線程的優先級。但這個並不總會如你所想設置了高優先級就一定最先執行。操作系統會優化調度,這也是線程不太好控制的原因之一

    3、靜態方法

    上面介紹的都是Tread的實例方法,Thread還有一些常用靜態方法。有時線程設置不當,會有些意想不到的的bug

    1.線程本地存儲

    AllocateDataSlot和AllocateNamedDataSlot用於給所有線程分配一個數據槽。像下面例子所示,如果不在子線程中給數據槽中放入數據,是獲取不到其他線程往裡面放的數據。

    var slot= Thread.AllocateNamedDataSlot("testSlot");
    //Thread.FreeNamedDataSlot("testSlot");
    Thread.SetData(slot, "hello kitty");
    Thread t1 = new Thread(() => {
        //Thread.SetData(slot, "hello kitty");
        var obj = Thread.GetData(slot);
        Console.WriteLine($"子線程:{obj}");//obj沒有值
    });
    t1.Start();

    var obj2 = Thread.GetData(slot);
    Console.WriteLine($"主線程:{obj2}");

    在聲明數據槽的時候.NET提醒我們如果要更好的性能,請使用ThreadStaticAttribute標記字段。什麼意思?我們來看下面這個例子

    //
    // 摘要:
    //     在所有線程上分配未命名的數據槽。 為了獲得更好的性能,請改用以 System.ThreadStaticAttribute 特性標記的字段。
    //
    // 返回結果:
    //     所有線程上已分配的命名數據槽。
    public static LocalDataStoreSlot AllocateDataSlot();

    例子中的如果不在靜態字段上標記ThreadStatic輸出結果就會一致。ThreadStatic標記指示各線程的靜態字段值是否唯一

    [ThreadStatic]
    static string name = string.Empty;
    public void Function()
    {
        name = "kitty";
        Thread t1 = new Thread(() => {
            Console.WriteLine($"子線程:{name}");//輸出空
        });
        t1.Start();
        Console.WriteLine($"主線程:{name}");//輸出kitty
    }

    還有一個ThreadLocal提供線程數據的本地存儲,用法和上面一樣,在每個線程中聲明數據僅供自己使用

    ThreadLocal<string> local = new ThreadLocal<string>() { };
    local.Value = "hello kitty";
    Thread t = new Thread(() => {
        Console.WriteLine($"子線程:{local.Value}");
    });
    t.Start();
    Console.WriteLine($"主線程:{local.Value}");

    上面的靜態方法用於線程的本地存儲TLS(Thread Local Storage),Thread.Sleep方法在開發調試時也是經常用的,讓線程掛起指定的時間來模擬耗時操作

    2.內存柵欄

    先說一個常識問題,為什麼我們發布版本時候要用Release發布?Release更小更快,做了很多優化,但優化對我們是透明的(計算機里透明認為是個黑盒子,內部邏輯細節對我們不開放,和生活中透明意味着完全掌握了解不欺瞞剛好相反),一般優化不會影響程序的運行,我們先借用網上的一個例子

    bool isStop = false;
    Thread t = new Thread(() => {
        bool isSuccess = false;
        while (!isStop)
        {
            isSuccess = !isStop;
        }
    });
    t.Start();
    Thread.Sleep(1000);
    isStop = true;
    t.Join();
    Console.WriteLine("主線程執行結束");

    上面例子如果在debug下能正確執行完直到輸出“主程序執行結束”,然而在release下卻一直會等待子線程的完成。這裏子線程中isStop一直為false。首先這是一個由多線程共享變量引起的問題,所以我們建議最好的解決辦法就是盡量不共享變量,其次可以使用Thread.MemoryBarrier和VolatileRead/Write以及其他鎖機制犧牲一點性能來換取數據的安全。(上面例子測試如果在子線程while中進行Console.writeLine操作,奇怪的發現release下也能正常輸出了,猜測應該是進行了內存數據的更新)

    release優化會將t線程中的isStop變量的值加載到CPU Cache中,而主線程修改了isStop值在內存中,所以子線程拿不到更新后的值,造成數據不一致。那麼解決辦法就是取值時從內存中獲取。Thread.MemoryBarrier()就可以讓在此方法之前的內存寫入都及時的從CPU Cache中更新到內存中,在此之後的內存讀取都要從內存中獲取,而不是CPU Cache。在例子中的while內增加Thread.MemoryBarrier()就能避免數據不一致問題。VolatileRead/Write是對MemoryBarrier的分開解釋,從處理器讀取,從處理器寫入。

    4、返回值

    前面聲明線程時,可以傳遞參數,那麼想要有返回值該如何去做呢?Thread並沒有提供返回值的操作,後面.NET給出的對Thead的高級封裝給出了解決方案,直接使用即可。那目前我們使用thread類就要自己實現下帶有返回值的線程操作,都是通過委託實現的,這裏簡單介紹一種,(共享外部變量也是可以,不建議)

    private Func<T> ThreadWithReturn<T>(Func<T> func)
    {
        T t = default(T);
        Thread thread = new Thread(() =>
        {
            t = func.Invoke();
        });
        thread.Start();
        return () =>

        {
            thread.Join();
            return t;
        };
    }
    //調用
    Func<intfunc = this.ThreadWithReturn<int>(() =>
    {
        Thread.Sleep(2000);
        return DateTime.Now.Millisecond;
    });
    int iResult = func.Invoke();

    二、線程池ThreadPool

    .NET起初提供Thread線程類,功能很豐富,API也很多,所以使用起來比較困難,況且線程還不都是很像理想中運行,所以從2.0開始提供了ThreadPool線程池靜態類,全是靜態方法,隱藏了諸多Thread的接口,讓線程使用起來更輕鬆。線程池可用於執行任務、發送工作項、處理異步 I/O、代表其他線程等待以及處理計時器

    1、工作隊列

    常用ThreadPool線程池靜態方法QueueUserWorkItem用於將方法排入線程池隊列中執行,如果線程池中有閑置線程就會執行,QueueUserWorkItem方法的參數可以指定一個回調函數委託並且傳入參數,像下面這樣

    ThreadPool.QueueUserWorkItem((obj) => {
                    Console.WriteLine($"線程池中線程  {Thread.CurrentThread.ManagedThreadId.ToString("00")} ,傳入 {obj.ToString()}");
                },"hello kitty");

    2、工作線程和IO線程

    一般異步任務的執行,不涉及到網絡文件等IO操作的,計算密集型,開發者來調用。而IO線程一般用在文件網絡上,是CLR調用的,開發者無需管。工作線程發起文件訪問調用,由驅動器完成后通知IO線程,IO線程則執行異步任務的回調函數

    獲取和設置最小最大的工作線程和IO線程

    ThreadPool.GetMaxThreads(out int workerThreads, out int completionPortThreads);
    ThreadPool.GetMinThreads(out int workerThreads, out int completionPortThreads);
    ThreadPool.SetMaxThreads(1616);
    ThreadPool.SetMinThreads(88);

    3、和Thread區別

    如果計算機只有8個核,同時可以有8個任務運行。現在我們有10個任務需要運行,用Thread就需要創建10個線程,用ThreadPool可能只需要利用8個線程就行,節約了空間和時間。線程池中的線程默認先啟動最小線程數量的線程,然後根據需要增減數量。線程池使用起來簡單,但也有一些限制,線程池中的線程都是後台線程,不能設置優先級,常用於耗時較短的任務。線程池中線程也可以阻塞等待,利用ManualResetEvent去通知,但一般不會使用。

    4、定時器

    .NET中有很多可以實現定時器的功能,在ThreadPool中,我們可以利用RegisterWaitForSingleObject來註冊一個指定時間的委託等待。像下面這樣,將每隔一秒就輸出消息

    ThreadPool.RegisterWaitForSingleObject(new AutoResetEvent(true), new WaitOrTimerCallback((obj, b) =>
    {
        Console.WriteLine($"obj={obj},tid={Thread.CurrentThread.ManagedThreadId},datetime={DateTime.Now}");
    }),"hello kitty",1000,false);

    我們平常見過比較多的還是timer類,timer類在.net內是好幾個地方都有的,在System.Threading、
    System.Timer、System.Windows.Form、System.Web.UI等裏面都有Timer,後面都是在第一個System.Threading里的Timer擴展

    System.Threading.Timer timer = new System.Threading.Timer((obj) =>
    {
        Console.WriteLine($"obj={obj},tid={Thread.CurrentThread.ManagedThreadId},datetime={DateTime.Now}");
    },"hello kitty",1000,1000);

    timer的底層有一個TimerQueue,利用ThreadPool.UnsafeQueueUserWorkItem來完成定時功能,和上面我們使用的ThreadPool定時器有一點區別

    實際開發中,簡單定時timer就夠用,但一般業務場景比較複雜,需要定製個性化的定時器,比如每月幾號執行,每月第幾個星期幾,幾點執行,工作日執行等。因此我們使用Quarz.NET定時框架,後面框架整合時會用到,用起來也是很簡單的

    先就啰嗦這兩點吧,下一篇應該是Task、Parallel以及Async/Await,然後總結介紹下C#的線程模式、線程同步鎖機制、異常處理,線程取消,線程安全集合和常見的線程問題

    天長水闊,見字如面,隨緣更新,拜了個拜~

    可關注主頁公號獲取更多哈

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

    【其他文章推薦】

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

    網頁設計一頭霧水??該從何著手呢? 找到專業技術的網頁設計公司,幫您輕鬆架站!

    ※想要讓你的商品成為最夯、最多人討論的話題?網頁設計公司讓你強力曝光

    ※想知道最厲害的台北網頁設計公司推薦台中網頁設計公司推薦專業設計師”嚨底家”!!

  • 二叉搜索樹BST(C語言實現可用)

    二叉搜索樹BST(C語言實現可用)

    1:概述

    搜索樹是一種可以進行插入,搜索,刪除等操作的數據結構,可以用作字典或優先級隊列。二叉搜索樹是最簡單的搜索樹。其左子樹的鍵值<=根節點的鍵值,右子樹的鍵值>=根節點的鍵值。

    如果共有n個元素,那麼每次操作需要的O(log n)的時間.

     

     

     

    常用知識點

    • 滿二叉樹 : 一棵深度為k,且有2^k-1個節點的二叉樹,稱為滿二叉樹。這種樹的特點是每一層上的節點數都是最大節點數。
    • 完全二叉樹 : 而在一棵二叉樹中,除最後一層外,若其餘層都是滿的,並且最後一層要麼是滿的,要麼在右邊缺少連續若干節點,則此二叉樹為完全二叉樹。具有n個節點的完全二叉樹的深度為floor(log2n)+1。深度為k的完全二叉樹,至少有2^(k-1)個恭弘=叶 恭弘子節點,至多有2^k-1個節點。

    2.基本操作

    1. 查找(search)
    2. 插入(insert)
    3. 刪除(remove)

    3:操作原理

      

    查找

    假設查找的值為x,從根節點的值開始比對,如果小於根節點的值,則往左兒子繼續查找,如果大於根節點的值,則往右兒子繼續查找.依次類推.直到當前節點的值等於要查找的值.

     

      以查找數值10為例

    插入

    按照查找的步驟即可找到插入值應該在的位置

     

     

    以插入數值6為例

    刪除:

    有四種情況:

    1: // 當前節點無左節點 ,右字節點7覆蓋5, 

    : 3: // 當前節點無右節點 ,右字節點7覆蓋5, 

     

     : 4: // 刪除節點5的左節點沒有右節點, 只需要8作為3的右節點 ,3節點覆蓋5

     

     

    : 2:  如果以上3中情況都沒有,只需要尋找當前節點的左節點的所有字節點的最大值,用最大值填充5節點 4填充5

     

     

     

     

    5:完整代碼

    #include <stdio.h> 
    #include <stdlib.h>
    struct TNode{
        int data;
        struct TNode *lt;
        struct TNode *rt;    
    };
    struct TNode* insrtTree(struct TNode *t,int key,int i);
    void printTree(struct TNode *root);
    struct TNode* delTree(struct TNode* t,int key);
    int find(struct TNode* t,int key); 
    int arr[1000]={0};
    int main(){
        int n,m;
        int i,t;
        scanf("%d%d",&n,&m); 
        struct TNode *root=NULL;
        for(i=0;i<n;i++){
            scanf("%d",&arr[i]); 
            root=insrtTree(root,arr[i],i);
        }
        //t=arr[m-1];
        
        /*
        if(arr[m-1]==0){
            printf("Right child");
        }else{
            printf("Light child");
        }*/
        root=delTree(root,10);
        printTree(root);
        return 0;
    }
    
    int find(struct TNode* pt,int key){
        if(pt==NULL)return NULL;
        else if(pt->data==key)return 1;
        else if(pt->data>key) return find(pt->lt,key);
        else if(pt->data<key) return find(pt->rt,key);
    }
    // 刪除節點 
    struct TNode* delTree(struct TNode* pt,int key){
        if(pt==NULL)return NULL;
        else if(pt->data>key) pt->lt=delTree(pt->lt,key);//尋找左節點 
        else if(pt->data<key) pt->rt=delTree(pt->rt,key);//尋找右節點
        //  找到節點 處理四種情況  
        else if(pt->lt==NULL){ // 當前節點無左節點 
            struct TNode* curt=pt->rt;
            free(pt);
            return curt;
        }else if(pt->rt==NULL){// 當前節點無右節點 
            struct TNode* curt=pt->lt;
            free(pt);
            return curt;
        }else if(pt->lt->rt==NULL){// 當前節點的左節點無右節點 
            struct TNode* curt=pt->lt;
            curt->rt=pt->rt;
            free(pt);
            return curt;
        }else{ 
        // 以上不滿足就把左兒子的子孫中最大的節點, 即右子樹的右子樹的...右子樹, 
        //提到需要刪除的節點位置
                struct TNode* p;
                for(p=pt->lt;p->rt->rt!=NULL;p=p->rt);
                struct TNode* curt=p->lt;
                p->rt=curt->rt;
                curt->lt=pt->lt;
                curt->rt=pt->rt;
                free(p);
                return curt;
        }
        return pt;
    }
    struct TNode* insrtTree(struct TNode *t,int key,int i){
        if(t==NULL){ //處理第一個節點 以及子節點為NULL情況 
            t=(struct TNode*)malloc(sizeof(struct TNode));
            t->lt=t->rt=NULL;
            t->data=key;
            return t;
        }
        if(t->data>key){// 插入左子樹情況 
             arr[i]=1;
            t->lt=insrtTree(t->lt,key,i);
        }else{         // 插入右子樹情況
            arr[i]=0;
            t->rt=insrtTree(t->rt,key,i);
        }
        return t;
    }
    void printTree(struct TNode *root){
        if(root==NULL)return;
        printf("%d ",root->data);
        printTree(root->lt);
        printTree(root->rt);
    }

     

    說明: 本身學習了 https://blog.csdn.net/li_l_il/article/details/88677927 但是完善了代碼 

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

    【其他文章推薦】

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

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

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

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

  • 區塊鏈和分佈式数字賬本正火?如何在7天內快速掌握這些必備的知識

    前言

    讀研期間,幾次被問到:“什麼是區塊鏈?”“我怎麼學習區塊鏈”。甚至跟“上至九十九”(爺爺奶奶),“下至剛會走的”(小學生的弟弟妹妹)解釋過我的研究內容。因此想總結一份7天的學習計劃(大量資料警告),讓那些對區塊鏈感興趣的人快速入門。區塊鏈技術的被運用到各行各業,尤其是各界(商界和政府)都對區塊鏈技術創新高度重視。本文總結了諸多入門區塊鏈的主要資源,博客、書籍和視頻,希望幫你用7天時間獲取必要的區塊鏈基礎知識。

    作者宇宙之一粟,轉載請先聲明出處
    公眾號宇宙之一粟,關注公眾號獲取更多相關資源

    介紹

    區塊鏈,剛開始聽起來會很新穎,因為是一個英文組合詞彙( Block + Chain )。區塊:存放數據的載體(想象成箱子),鏈:把這些箱子首尾相連(類似數據結構中的單鏈表)。

    區塊鏈的本質:一個去中心化的分佈式賬本數據庫。其本身是一串使用密碼學相關聯所產生的數據塊,每一個數據塊中包含了多次比特幣網絡交易有效確認的信息。

    區塊鏈技術從比特幣中發展而來,是比特幣的底層技術,和比特幣是相伴相生的關係。目前這項技術已經不僅僅限於比特幣——青出於藍而勝於藍。各行各業開始利用這項技術尋求突破。

    2019年6月,Facebook宣布了其加密貨幣項目——。

    我們國家央行也將發行自己的数字貨幣——( Digital Currency Electronic Payment ),也採用了區塊鏈技術,目前仍處於研究測試過程中。

    2019年10月24日下午,。一時間區塊鏈技術又衝上了風口。

    因此,我們有必要對區塊鏈技術做一個基本的了解。

    如何獲得知識

    如果想快速學習區塊鏈知識:收聽音頻課,閱讀書籍,看論文或在線文章,學習白皮書以及參与區塊鏈的相關學習計劃或在線課程。其他針對想從事更加專業的學習人員——參加編程或智能合約編碼課程。

    應該學習到什麼程度

    在區塊鏈領域工作或打算工作的每個人至少應該能夠理解並編寫一個非常簡單的智能合約,例如以程序語言Solidity通過幾行代碼實現的託管過程。儘管其他人會說,在學習區塊鏈和DLT時應該把重點放在另一個方面,但在我們看來,這是一條清晰的聲明。

    在我們看來,理解簡單的智能合約(例如5-10行代碼)的需求不僅對於信息系統領域的員工很重要,而且在商業,經濟和法律領域也很重要。但是,關於如何配置節點的更深入的技術知識通常不是緊要的,但以後可以獲取。

    任何尋求參与區塊鏈技術並考慮以下步驟的人都可能擁有光榮的職業生涯。我們認為,區塊鏈技術及其日益重要的潛力有可能對感興趣的人的職業道路產生积極影響,因為在這個動態且快速增長的細分市場中,未來幾年甚至數十年內還有很多工作要做。這樣,可以將由於数字化和自動化程度提高而失業(例如在金融部門)的風險降到最低。

    但是感興趣的人如何獲得足夠的知識呢?存在哪些研究區塊鏈技術的機會?本文總結了區塊鏈教育的一些不同策略。我們基本上設計了一個特定的程序,以在大約7個工作日內實現“區塊鏈入門”。

    一、購買或轉讓加密貨幣

    所需時間:0.5天

    除了獲得一些理論知識之外,理解此技術非常重要的是您在操作上“弄髒手”。 它的工作方式如下,為感興趣的人提供有關什麼是區塊鏈技術的最重要學習。

    因此,開始的最佳練習是:購買加密貨幣(例如比特幣)並在全球範圍內進行轉移。 如下所示,請找到分步指南:

    • 在例如或比特派上開設一個帳戶;其他選擇:Bitstamp,Bitrex,Binance。
    • 購買比特幣或者購買以太幣。請注意,萬一使用公鑰或私鑰出錯,這筆錢將不可避免地丟失。因此,遵循此步驟當然是每個人自己的決定。
    • 開設第二個帳戶(上面的示例)。
    • 從第二個帳戶獲取一個錢包地址,該地址類似於以太坊的0xd42899dcC146d4788649e6aa5B09f129fC269127。
    • 第一步,將您購買的一部分以太幣或比特幣轉移到該地址。請注意,以太幣和比特幣的地址不同,因此請謹慎行事,切勿混淆。
    • 現在,您可以看到可以在幾秒鐘(以太)或幾分鐘(比特幣)內將價值發送到世界各地。
    • 一個更高級的步驟,但對理解區塊鏈非常有幫助:將插件添加到Google Chrome互聯網瀏覽器中,以直接訪問以太坊網絡並將您的以太幣存儲在您自己的錢包中。之後,開設一個帳戶並生成您自己的錢包地址。然後,將您的一些以太幣從之前的步驟轉移到這個新生成的錢包中。

    二、音頻課

    所需時間:1.5天

    如果你喜歡聽音頻課,選擇一個合適的音頻可以快速入門:

    • Kryptoshow: Julian Hosp博士很好地介紹了區塊鏈技術和加密貨幣這一主題。播客還涵蓋了高級方面,例如在密碼學和編程方面。在訪問播客。
    • BTC Echo:此播客面向更高級的受眾,重點關注比特幣和加密資產。在訪問播客。
    • 從0到1全面學透區塊鏈音頻教程,在學習

    三、閱讀重要的白皮書

    所需時間:1天

    為了了解區塊鏈技術的起源和概念,有必要研究兩種最重要的加密貨幣比特幣和以太坊的白皮書。其他補充Filecoin白皮書。

    最重要的論文:

    • 比特幣白皮書:中本聰(2008):比特幣:點對點电子現金系統,。
    • 以太坊白皮書:Buterin,V.(2013):以太坊白皮書:下一代智能合約和去中心化應用平台, 。
    • Filecoin白皮書: Protocol Labs(2017):Filecoin: A Decentralized Storage Network,
      (待完善)

    四、觀看視頻

    所需時間:2天

    在通過閱讀有關比特幣和以太坊的原始著作從“科學”角度看待區塊鏈技術之後,您可以使用視頻進一步熟悉該技術並更深入地了解該技術的不同組成部分。我們推薦以下視頻:

    最重要的視頻:

    五、更多文章和網站

    所需時間:1天

    通過遵循建議的步驟,您現在應該已經對技術有了基本的高級知識。現在,是時候更深入地研究區塊鏈技術了。我們建議閱讀以下文章:

    文章或文檔:

    需要了解的項目的網站:

    • 以太坊:
    • EOS:
    • NULS:
    • FISCO BCOS:

    六、更廣泛概述的書籍

    所需時間:2天閱讀

    其他書籍:

    • 中文版(第2版)
    • Andreas M. Antonopoulos / Gavin Wood(2018年):

    Ps: 關注公眾號 宇宙之一粟 回復關鍵字 “區塊鏈” 獲取电子版

    七、認識志同道合之人

    所需時間:參加2次聚會(主要是免費)

    下一步,我們建議您進入區塊鏈社區,並與區塊鏈專家進行首次討論。

    科學論文

    所需時間:0天,因為這是可選的

    如果您打算從科學的角度更多地探討區塊鏈的話題,那麼就有可能研究有關區塊鏈技術的論文。我們將進一步擴大此列表。

    文件:

    • Eyal I , Gencer A E , Sirer E G , et al.
    • Gilad, Yossi & Hemo, Rotem & Micali, Silvio & Vlachos, Georgios & Zeldovich, Nickolai. (2017).
    • Li C , Li P , Zhou D , et al.
    • Yin M , Malkhi D , Reiter M K , et al.
    • Wang, Jiaping & Wang, Hao. (2019).
    • 更多區塊鏈相關論文

    現在?

    重要的是“閱讀”有關區塊鏈和DLT中的教育如何工作的信息。歸根結底,只有一件重要的事情:那就去做。不要只是想,而要行動。

    歡迎評論給我,無論您是否遵循我的建議–並向我提供反饋。如果您還有其他想法,請告訴我們如何學習和使用區塊鏈。如果您使用其他來源來獲取或增加您的區塊鏈知識,那麼如果您能與我分享這些知識,我將非常感激。

    備註

    在Medium看到Education in Blockchain and DLT: How to Acquire the Necessary Knowledge with a Workload of 10 Working Days的一篇博客,但是有很多網站和學習資料使我們不能訪問的。基於此博客,製作了方便我們快速學習並掌握區塊鏈必備知識的這篇文章。

    如果您喜歡本文,將其轉發或分享(附上原文出處),我將非常高興並表示感謝。
    也歡迎關注我的微信公眾號:宇宙之一粟,分享更多資料,與你讀書學習精進。

    參考博客: Authors: Philipp Sandner, Jonas Groß

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

    【其他文章推薦】

    台北網頁設計公司這麼多,該如何挑選?? 網頁設計報價省錢懶人包"嚨底家"

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

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

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

  • JVM原理速記複習Java虛擬機總結思維導圖面試必備

    JVM原理速記複習Java虛擬機總結思維導圖面試必備

    良心製作,右鍵另存為保存

    喜歡可以點個贊哦

    Java虛擬機

    一、運行時數據區域

    線程私有

    • 程序計數器

      • 記錄正在執行的虛擬機字節碼指令的地址(如果正在執行的是Native方法則為空),是唯一一個沒有規定OOM(OutOfMemoryError)的區域。
    • Java虛擬機棧

      • 每個Java方法在執行的同時會創建一個棧楨用於存儲局部變量表、操作數棧、動態鏈接、方法出口等信息。從方法調用直到執行完成的過程,對應着一個棧楨在Java虛擬機棧中入棧和出棧的過程。(局部變量包含基本數據類型、對象引用reference和returnAddress類型)
    • 本地方法棧

      • 本地方法棧與Java虛擬機棧類似,它們之間的區別只不過是本地方法棧為Native方法服務。

    線程公有

    • Java堆(GC區)(Java Head)

      • 幾乎所有的對象實例都在這裏分配內存,是垃圾收集器管理的主要區域。分為新生代和老年代。對於新生代又分為Eden空間、From Survivor空間、To Survivor空間。
    • JDK1.7 方法區(永久代)

      • 用於存放已被加載的類信息、常量、靜態變量、即時編譯器編譯后的代碼等數據。
        對這塊區域進行垃圾回收的主要目的是對常量池的回收和對類的卸載,但是一般難以實現。
        HotSpot虛擬機把它當做永久代來進行垃圾回收。但很難確定永久代的大小,因為它受到很多因素的影響,並且每次Full GC之後永久代的大小都會改變,所以經常拋出OOM異常。
        從JDK1.8開始,移除永久代,並把方法區移至元空間。
      • 運行時常量池

        • 是方法區的一部分
          Class文件中的常量池(編譯器生成的字面量和符號引用)會在類加載后被放入這個區域。
          允許動態生成,例如String類的intern()
    • JDK1.8 元空間

      • 原本存在方法區(永久代)的數據,一部分移到了Java堆裏面,一部分移到了本地內存裏面(即元空間)。元空間存儲類的元信息,靜態變量和常量池等放入堆中。
    • 直接內存

      • 在NIO中,會使用Native函數庫直接分配堆外內存。

    二、HotSpot虛擬機

    對象的創建

    • 當虛擬機遇到一條new指令時
    1. 檢查參數能否在常量池中找到符號引用,並檢查這個符號引用代表的類是否已經被加載、解析和初始過,沒有的話先執行相應的類加載過程。
    2. 在類加載檢查通過之後,接下來虛擬機將為新生對象分配內存。
    3. 內存分配完成之後,虛擬機需要將分配到的內存空間都初始化為零值(不包括對象頭)。
    4. 對對象頭進行必要的設置。
    5. 執行構造方法按照程序員的意願進行初始化。

    對象的內存布局

      1. 對象頭
        1. 第一部分用於存儲對象自身的運行時數據,如哈希碼、GC分代年齡、鎖狀態標識、線程持有的鎖、偏向線程ID、偏向實現戳等。
        1. 第二部分是類型指針,即對象指向它的類元數據的指針(如果使用直接對象指針訪問),虛擬機通過這個指針來確定這個對象是哪個類的實例。
        1. 如果對象是一個Java數組的話,還需要第三部分記錄數據長度的數據。
      1. 實例數據
      • 是對象真正存儲的有效信息,也就是在代碼中定義的各種類型的字段內容。
      1. 對齊填充
      • 不是必然存在的,僅僅起着佔位符的作用。
        HotSpot需要對象的大小必須是8字節的整數倍。

    對象的訪問定位

    • 句柄訪問

      • 在Java堆中劃分出一塊內存作為句柄池。
        Java棧上的對象引用reference中存儲的就是對象的句柄地址,而句柄中包含了到對象實例數據的指針和到對象類型數據的指針。
        對象實例數據在Java堆中,對象類型數據在方法區(永久代)中。
        優點:在對象被移動時只會改變句柄中的實例數據指針,而對象引用本身不需要修改。
    • 直接指針訪問(HotSpot使用)

      • Java棧上的對象引用reference中存儲的就是對象的直接地址。
        在堆中的對象實例數據就需要包含到對象類型數據的指針。
        優點:節省了一次指針定位的時間開銷,速度更快。

    三、垃圾收集

    概述

    • 垃圾收集主要是針對Java堆和方法區。
      程序計數器、Java虛擬機棧個本地方法棧三個區域屬於線程私有,線程或方法結束之後就會消失,因此不需要對這三個區域進行垃圾回收。

    判斷對象是否可以被回收

    • 第一次標記(緩刑)

      • 引用計數算法

        • 給對象添加一個引用計數器,當對象增加一個引用時引用計數值++,引用失效時引用計數值–,引用計數值為0時對象可以被回收。

    但是它難以解決對象之間的相互循環引用的情況,此時這個兩個對象引用計數值為1,但是永遠無法用到這兩個對象。

    - 可達性分析算法(Java使用)
    
        - 以一系列GC Roots的對象作為起始點,從這些節點開始向下搜索,搜索所走過的路徑稱為引用鏈,當一個對象到GC Roots沒有任何引用鏈相連是,則證明此對象不可用,可以被回收。

    GC Roots對象包括

    1. 虛擬機棧(棧楨中的本地變量表)中引用的對象。
    2. 方法區中共類靜態屬性引用的對象。
    3. 方法區中常量引用的對象。
    4. 本地方法棧中JNI(即一般說的Native方法)引用的對象。
    • 第二次標記

      • 當對象沒有覆蓋finalize()方法,或者finalize()方法已經被虛擬機調用過。
        如果對象在finalize方法中重新與引用鏈上的任何一個對象建立關聯則將不會被回收。
      • finalize()

        • 任何一個對象的finalize()方法都只會被系統調用一次。
          它的出現是一個妥協,運行代價高昂,不確定性大,無法保證各個對象的調用順序。
          finalize()能做的所有工作使用try-finally或者其他方式都可以做的更好,完全可以忘記在這個函數的存在。

    方法區的回收

    • 在方法區進行垃圾回收的性價比一般比較低。
      主要回收兩部分,廢棄常量和無用的類。

    滿足無用的類三個判斷條件才僅僅代表可以進行回收,不是必然關係,可以使用-Xnoclassgc參數控制。

    1. 該類的所有實例都已經被回收,也就是Java堆中不存在該類的任何實例。
    2. 加載該類的ClassLoader已經被回收。
    3. 該類對應的java.lang.Class對象沒有在任何地方被引用,無法在任何地方通過反射訪問到該類的方法。

    引用類型

      1. 強引用
      • 使用new一個新對象的方式來創建強引用。
        只要強引用還存在,被引用的對象則永遠不會被回收。
      1. 軟引用
      • 使用SoftReference類來實現軟引用。
        用來描述一些還有用但是並非必須的對象,被引用的對象在將要發生內存溢出異常之前會被回收。
      1. 弱引用
      • 使用WeakReference類來實現弱引用。
        強度比軟引用更弱一些,被引用的對象在下一次垃圾收集時會被回收。
      1. 虛引用
      • 使用PhantomReference類來實現虛引用。
        最弱的引用關係,不會對被引用的對象生存時間構成影響,也無法通過虛引用來取得一個對象實例。
        唯一目的就是能在這個對象被收集器回收時收到一個系統通知。

    垃圾收集算法

      1. 標記 – 清除
      • 首先標記出所有需要回收的對象,在標記完成后統一回收被標記的對象並取消標記。

    不足:

    1. 效率問題,標記和清除兩個過程的效率都不高。
    2. 空間問題,標記清除之後會產生大量不連續的內存碎片,沒有連續內存容納較大對象而不得不提前觸發另一次垃圾收集。
      1. 標記 – 整理
      • 和標記 – 清除算法一樣,但標記之後讓所有存活對象都向一段移動,然後直接清理掉端邊界以外的內存。
        解決了標記 – 清除算法的空間問題,但需要移動大量對象,還是存在效率問題。
      1. 複製
      • 將可用內存按容量劃分為大小相等的兩塊,每次只使用其中的一塊。當這一塊的內存用完了,就將還存活着的對象複製到另外一塊上面,然後再把已使用多的內存空間一次清理掉。
        代價是將內存縮小為原來的一般,太高了。

    現在商業虛擬機都採用這種算法用於新生代。
    因為新生代中的對象98%都是朝生暮死,所以將內存分為一塊較大的Eden空間和兩塊較小的Survivor空間,每次使用Eden和其中一塊Survivor空間。
    當回收時,如果另外一塊Survivor空間沒有足夠的空間存放存活下來的對象時,這些對象將直接通過分配擔保機制進入老年代。

      1. 分代收集
      • 一般把Java堆分為新生代和老年代。
        在新生代中使用複製算法,在老年代中使用標記 -清除 或者 標記 – 整理 算法來進行回收。

    HotSpot的算法實現

    • 枚舉根節點(GC Roots)

      • 目前主流Java虛擬機使用的都是準確式GC。
        GC停頓的時候,虛擬機可以通過OopMap數據結構(映射表)知道,在對象內的什麼偏移量上是什麼類型的數據,而且特定的位置記錄著棧和寄存器中哪些位置是引用。因此可以快速且準確的完成GC Roots枚舉。
    • 安全點

      • 為了節省GC的空間成本,並不會為每條指令都生成OopMap,只是在“特定的位置”記錄OopMap,這些位置稱為安全點。

    程序執行只有到達安全點時才能暫停,到達安全點有兩種方案。

    1. 搶斷式中斷(幾乎不使用)。GC時,先把所有線程中斷,如果有線程不在安全點,就恢復該線程,讓他跑到安全點。
    2. 主動式中斷(主要使用)。GC時,設置一個標誌,各個線程執行到安全點時輪詢這個標誌,發現標誌為直則掛起線程。

    但是當線程sleep或blocked時無法響應JVM的中斷請求走到安全點中斷掛起,所以引出安全區域。

    • 安全區域

      • 安全區域是指在一段代碼片段之中,引用關係不會發生變化,是擴展的安全點。

    線程進入安全區域時表示自己進入了安全區域,這個發生GC時,JVM就不需要管這個線程。
    線程離開安全區域時,檢查系統是否完成GC過程,沒有就等待可以離開安全區域的信號為止,否者繼續執行。

    垃圾收集器

    • 新生代

        1. serial收集器
        • 它是單線程收集器,只會使用一個線程進行垃圾收集工作,更重要的是它在進行垃圾收集時,必須暫停其他所有的工作線程。

    優點:對比其他單線程收集器簡單高效,對於單個CPU環境來說,沒有線程交互的開銷,因此擁有最高的單線程收集效率。

    它是Client場景下默認新生代收集器,因為在該場景下內存一般來說不會很大。

    - 2. parnew收集器
    
        - 它是Serial收集器的多線程版本,公用了相當多的代碼。

    在單CPU環境中絕對不會有比Serial收集器更好的效果,甚至在2個CPU環境中也不能百分之百超越。

    它是Server場景下默認的新生代收集器,主要因為除了Serial收集器,只用它能與CMS收集器配合使用。

    - 3. parallel scavenge收集器
    
        - “吞吐優先”收集器,與ParNew收集器差不多。

    但是其他收集器的目標是盡可能縮短垃圾收集時用戶線程停頓的時間,而它的目標是達到一個可控制的吞吐量。這裏的吞吐量指CPU用於運行用戶程序的時間佔總時間的比值。

    • 老年代

        1. serial old收集器
        • 是Serial收集器老年代版本。

    也是給Client場景下的虛擬機使用的。

    - 5. parallel old收集器
    
        - 是Parallel Scavenge收集器的老年代版本。

    在注重吞吐量已經CPU資源敏感的場合,都可以優先考慮Parallel Scavenge和Parallel Old收集器。

    - 6. cms收集器
    
        - Concurrent Mark Sweep收集器是一種以獲取最短回收停頓時間為目標的收集器。
        - 運作過程
    
            - 1. 初始標記(最短)。仍需要暫停用戶線程。只是標記一下GC Roots能直接關聯到的對象,速度很快
    1. 併發標記(耗時最長)。進行GC Roots Tracing(根搜索算法)的過程。
    2. 重新標記。修正併發標記期間因用戶程序繼續運作而導致標記產生變動的那一部分對象的標記記錄。比初始標記長但遠小於併發標記時間。
    3. 併發清除

    1 和4 兩個步驟並沒有帶上併發兩個字,即這兩個步驟仍要暫停用戶線程。

        - 優缺點
    
            - 併發收集、低停頓。
    1. CMS收集器對CPU資源非常敏感。雖然不會導致用戶線程停頓,但是佔用CPU資源會使應用程序變慢。
    2. 無法處理浮動垃圾。在併發清除階段新垃圾還會不斷的產生,所以GC時要控制“-XX:CMSinitiatingOccupancyFraction參數”預留足夠的內存空間給這些垃圾,當預留內存無法滿足程序需要時就會出現”Concurrent Mode Failure“失敗,臨時啟動Serial Old收集。
    3. 由於使用標記 – 清除算法,收集之後會產生大量空間碎片。
      1. g1收集器
      • Garbage First是一款面向服務端應用的垃圾收集器
      • 運作過程

          1. 初始標記
    1. 併發標記
    2. 最終標記
    3. 刪選標記

    五、類加載機制

    概述

    • 虛擬機把描述類的數據從Class問價加載到內存,並對數據進行校驗、轉換解析和初始化,最終形成可以被虛擬機直接使用的Java類型。
      Java應用程序的高度靈活性就是依賴運行期動態加載和動態連接實現的。

    類的生命周期

    • 加載 -> 連接(驗證 -> 準備 -> 解析) -> 初始化 -> 使用 – >卸載

    類初始化時機

    • 主動引用

      • 虛擬機規範中沒有強制約束何時進行加載,但是規定了有且只有五種情況必須對類進行初始化(加載、驗證、準備都會隨之發生)
    1. 遇到new、getstatic、putstatic、invokestatic這四條字節碼指令時沒有初始化。
    2. 反射調用時沒有初始化。
    3. 發現其父類沒有初始化則先觸發其父類的初始化。
    4. 包含psvm(mian()方法)的那個類。
    5. 動態語言支持時,REF_getStatic、REF_putStatic、REF_invokeStatic的方法句柄。
    • 被動引用

      • 除上面五種情況之外,所有引用類的方式都不會觸發初始化,稱為被動引用。
    1. 通過子類引用父類的靜態字段,不會導致子類的初始化。
    2. 通過數組定義來引用類,不會觸發此類的初始化。該過程會對數組類進行初始化,數組類是一個由虛擬機自動生成的、直接繼承Object的子類,其中包含數組的屬性和方法,用戶只能使用public的length和clone()。
    3. 常量在編譯階段會存入調用類的常量池中,本質上並沒有直接引用到定義常量的類,因此不會觸發定義常量的類的初始化。

    類加載過程

      1. 加載
        1. 通過類的全限定名來獲取定義此類的二進制字節流。
    1. 將這個字節流所代表的靜態存儲結構轉化為方法區的運行時數據結構。
    2. 在內存中生成一個代表這個類的java.lang.Class對象(HotSpot將其存放在方法區中),作為方法區這個類的各種數據的訪問入口。
      1. 驗證
      • 為了確保Class文件的字節類中包含的信息符合當前虛擬機的要求,並且不會危害虛擬機自身的安全。可以通過-Xverify:none關閉大部分類驗證。
    1. 文件格式驗證。確保輸入字節流能正確的解析並存儲於方法區,後面的3個驗證全部基於方法區的存儲結構進行,不會再操作字節流。
    2. 元數據驗證。對字節碼描述信息進行語義分析,確保其符合Java語法規範。(Java語法驗證)
    3. 字節碼驗證。最複雜,通過數據流和控制流分析,確定程序語義時合法的、符合邏輯的。可以通過參數關閉。(驗證指令跳轉範圍,類型轉換有效等)
    4. 符號引用驗證。將符號引用轉化為直接引用,發生在第三個階段——解析階段中發生。
      1. 準備
      • 類變量是被static修飾的變量,準備階段為類變量分配內存並設置零值(final直接設置初始值),使用的是方法區的內存。
      1. 解析
      • 將常量池內的符號引用替換為直接引用的過程。
        其中解析過程在某些情況下可以在初始化階段之後再開始,這是為了支持Java的動態綁定。
        解析動作主要針對類或接口、字段、類方法、接口方法、方法類型、方法句柄、和調用點限定符。
      1. 初始化
      • 初始化階段才真正執行類中定義的Java程序代碼,是執行類構造器 ()方法的過程。
        在準備階段,類變量已經給過零值,而在初始化階段,根據程序員通過程序制定的主觀計劃去初始化類變量和其他資源。

        • ()

          • 類構造器方法。是由編譯器自動收集類中的所有類變量的賦值動作和靜態語句塊中的的語句合併產生的。
    1. 不需要顯式調用父類構造器,JVM會保證在子類clinit執行之前,父類的clinit已經執行完成。
    2. 接口中不能使用靜態語句塊但仍可以有類變量的賦值操作。當沒有使用父接口中定義的變量時子接口的clinit不需要先執行父接口的clinit方法。接口的實現類也不會執行接口的clinit方法。
    3. 虛擬機會保證clinit在多線程環境中被正確的加鎖、同步。其他線性喚醒之後不會再進入clinit方法,同一個類加載器下,一個類型只會初始化一次。

       - <init>()
      
           - 對象構造器方法。Java對象被創建時才會進行實例化操作,對非靜態變量解析初始化。
    4. 會顯式的調用父類的init方法,對象實例化過程中對實例域的初始化操作全部在init方法中進行。

    類(加載) 器

    • 類與類加載器

      • 類加載器實現類的加載動作。
        類加載器和這個類本身一同確立這個類的唯一性,每個類加載器都有獨立的類命名空間。在同一個類加載器加載的情況下才會有兩個類相等。
        相等包括類的Class對象的equals()方法、isAssignableFrom()方法、isInstance()、instanceof關鍵字。
    • 類加載器分類

      • 啟動類加載器

        • 由C++語言實現,是虛擬機的一部分。負責將JAVA_HOME/lib目錄中,或者被-Xbootclasspath參數指定的路徑,但是文件名要能被虛擬機識別,名字不符合無法被啟動類加載器加載。啟動類加載器無法被Java程序直接引用。
      • 擴展類加載器

        • 由Java語言實現,負責加載JAVA_HOME/lib/ext目錄,或者被java.ext.dirs系統變量所指定的路徑中的所有類庫,開發者可以直接使用擴展類加載器。
      • 應用程序類加載器

        • 由於這個類加載器是ClassLoader中的getSystemClassLoader()方法的返回值,所以一般也稱他為系統類加載器。負責加載用戶類路徑(ClassPath)上所指定的類庫,一般情況下這個就是程序中默認的類加載器。
      • 自定義類加載器

        • 由用戶自己實現。
    1. 如果不想打破雙親委派模型,那麼只需要重寫findClass方法即可。
    2. 否則就重寫整個loadClass方法。
    • 雙親委派模型

      • 雙親委派模型要求除了頂層的啟動類加載器外,其餘的類加載器都應該有自己的父類加載器。父子不會以繼承的關係類實現,而是都是使用組合關係來服用父加載器的代碼。
        在java.lang.ClassLoader的loadClass()方法中實現。
      • 工作過程

        • 一個類加載器首先將類加載請求轉發到父類加載器,只有當父類加載器無法完成(它的搜索範圍中沒有找到所需要的類)時才嘗試自己加載
      • 好處

        • Java類隨着它的類加載器一起具備了一種帶有優先級的層次關係,從而使得基礎類庫得到同意。

    四、內存分配與回收策略

    Minor GC 和 Full GC

    • Minor GC

      • 發生在新生代的垃圾收集動作,因為新生代對象存活時間很短,因此Minor GC會頻繁執行,執行速度快。
      • 時機

        • Eden不足
    • Full GC

      • 發生在老年區的GC,出現Full GC時往往伴隨着Minor GC,比Minor GC慢10倍以上。
      • 時機

          1. 調用System.gc()
          • 只是建議虛擬機執行Full GC,但是虛擬機不一定真正去執行。
            不建議使用這種方式,而是讓虛擬機管理內存。
          1. 老年代空間不足
          • 常見場景就是大對象和長期存活對象進入老年代。
            盡量避免創建過大的對象以及數組,調大新生代大小,讓對象盡量咋新生代中被回收,不進入老年代。
          1. JDK1.7 之前方法區空間不足
          • 當系統中要加載的類、反射的類和常量較多時,永久代可能會被佔滿,在未配置CMS GC的情況下也會執行Full GC,如果空間仍然不夠則會拋出OOM異常。
            可採用增大方法區空間或轉為使用CMS GC。
          1. 空間分配擔保失敗
          • 發生Minor GC時分配擔保的兩個判斷失敗
          1. Concurrent Mode Failure
          • CMS GC 併發清理階段用戶線程還在執行,不斷有新的浮動垃圾產生,當預留空間不足時報Concurrent Mode Failure錯誤並觸發Full GC。

    內存分配策略

      1. 對象優先在Eden分配
      • 大多數情況下,對象在新生代Eden上分配,當Eden空間不夠時,發起Minor GC,當另外一個Survivor空間不足時則將存活對象通過分配擔保機制提前轉移到老年代。
      1. 大對象直接進入老年代
      • 配置參數-XX:PretenureSizeThreshold,大於此值得對象直接在老年代分配,避免在Eden和Survivor之間的大量內存複製。
      1. 長期存活對象進入老年代
      • 虛擬機為每個對象定義了一個Age計數器,對象在Eden出生並經過Minor GC存活轉移到另一個Survivor空間中時Age++,增加到默認16則轉移到老年代。
      1. 動態對象年齡綁定
      • 虛擬機並不是永遠要求對象的年齡必須到達MaxTenuringThreshold才能晉陞老年代,如果在Survivor中相同年齡所有對象大小總和大於Survivor空間的一半,則年齡大於或等於該年齡的對象直接進入老年代。
      1. 空間分配擔保
      • 在發生Minor GC之前,虛擬機先檢查老年代最大可用的連續空間是否大於新生代的所有對象,如果條件成立,那麼Minor GC可以認為是安全的。
        可以通過HandlePromotionFailure參數設置允許冒險,此時虛擬機將與歷代晉陞到老年區對象的平均大小比較,仍小於則要進行一次Full GC。
        在JDK1.6.24之後HandlePromotionFailure已無作用,即虛擬機默認為true。

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

    【其他文章推薦】

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

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

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

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

  • 痞子衡嵌入式:串行EEPROM接口事實標準及SPI EEPROM簡介

    痞子衡嵌入式:串行EEPROM接口事實標準及SPI EEPROM簡介

      大家好,我是痞子衡,是正經搞技術的痞子。今天痞子衡給大家介紹的是EEPROM接口標準及SPI EEPROM

      痞子衡之前寫過一篇文章 ,介紹過并行NOR Flash基本概念。眾所周知,現如今嵌入式非易失性存儲器基本被NOR Flash一統江湖了,但在Flash技術發明之前,EEPROM才是非易失性存儲器的霸主。EEPROM的全稱是”電可擦除可編程只讀存儲器”,即Electrically Erasable Programmable Read-Only Memory,EEPROM技術的發明可是拯救過一大批嵌入式工程師的,畢竟在這之前非易失性存儲器技術的演進分別是ROM(只讀), PROM(只能寫一次), EPROM(紫外線可擦除),擦除方式都不太友好,直到EEPROM的出現才變得人性化。雖說現在Flash是主流,但在較低容量(2Mb以下)尤其是超低容量(1Kb以下)的市場,EEPROM仍然有其不可替代的應用場合。今天痞子衡就來好好聊一聊EEPROM:

    一、EEPROM背景簡介

      聊到EEPROM發展史,不得不提浮柵MOSFET,這是一項發明於1967年的技術,它是所有閃存的基礎。1970年,第一款成功的浮柵型器件-EPROM被發明。1979年,大名鼎鼎的SanDisk(閃迪)創始人Eli Harari,發明了世界上首個電可擦除的浮柵型器件即EEPROM。
      講到EEPROM必然要將它和與其相愛相殺的Flash一起對比。關於Flash大家都很熟悉,但其實Flash全稱應該叫Flash EEPROM,它屬於廣義的EEPROM。而本文主角EEPROM,指的是狹義的EEPROM,Flash和EEPROM最大的區別是:Flash按扇區操作,EEPROM按字節操作。Flash的特點是結構簡單,容量可以做得比較大且在大數據量下的操作速度更快,但缺點是操作過程麻煩,所以Flash適於當不需頻繁改寫的程序存儲器。而在有些應用中往往需要頻繁的改寫某些小量數據且需掉電非易失,傳統結構的EEPROM則非常適合。
      EEPROM不像NOR, NAND Flash技術演進得那麼複雜,因此實際上關於EEPROM並沒有成文的標準,即使最知名的电子行業標準之一JEDEC也沒有關於EEPROM的標準出台,不過各大廠商生產的EEPROM似乎都遵從某種約定的事實標準,這在後面介紹的EEPROM接口命令里顯得尤為明顯。

    二、Serial EEPROM原理

    2.1 Serial EEPROM分類

      從軟件驅動開發角度而言,Serial EEPROM可以從以下幾個方面進一步細分:

    地址碼長度:1byte / 2byte / 3byte
    通信接口類型:I2C / SPI / Microwire / UNIO Bus / Single-Wire

      本文的主要研究對象是SPI接口的EEPROM。

    2.2 SPI EEPROM內存模型

      EEPROM內存單元從大到小一般分為如下4層:Device、Sector、Page、Byte,其中Sector不是必有的,並且Page也只是個結構概念,跟NOR Flash里的Page/Sector意義不一樣,因為Byte就是EEPROM讀寫的最小單元(即可以任意地址隨機訪問),所以你可以把EEPROM當做一個非易失性的RAM。當然有些高端EEPROM中集成了Page/Sector操作命令,這隻是為了讓EEPROM操作效率更高而已。

    2.3 SPI EEPROM信號與封裝

      SPI EEPROM一般有8個腳,除去電源Vcc,地GND/Vss,以及SPI四根信號線(CS#, SCK, SI, SO)不言而喻之外,還有兩根特殊的控制信號,即WP#(寫保護)和HOLD#(掛起)。WP#信號主要是從硬件層面上對EEPROM內存進行保護,防止電路上的噪聲干擾篡改了EEPROM里的內容;而HOLD#則提供EEPROM寫操作暫停的功能,當該信號有效的時候,SI信號輸入將被忽略,因此主機可以做其他更高優先級的事情。

      SPI EEPROM雖然只有8pin,但是封裝種類還是比較齊全的,這其中最經典的當屬JEDEC定義的8-lead SOIC,此外還有TSSOP8, UDFN8, WLCSP8,下圖羅列了常見封裝:

    2.4 SPI EEPROM接口命令

    2.4.1 事實標準

      痞子衡在文章開頭的時候講過,SPI EEPROM並沒有什麼成文的接口命令標準,但是各大廠商生產的SPI EEPROM無一例外都支持下錶的6條命令,即READ(讀內存)、WRITE(寫內存)、WREN(寫使能)、WRDI(寫禁止)、RDSR(讀狀態寄存器)、WRSR(寫狀態寄存器),所以從軟件接口層面而言,這6條命令就是SPI EEPROM事實上的接口命令標準。

      除了6條標準命令外,SPI EEPROM內部還有一個8bit的狀態寄存器,用於反饋命令執行狀態,這8bit狀態寄存器的位定義也是存在如下錶所示的事實標準的:

      不考慮寫保護特性的話,bit0 – RDY#和bit1 – WEL是比較常用的,RDY#位主要用於標示所有涉及改變內存或狀態寄存器的命令的執行結果,WEL位則保存了上一次WREN和WRDI命令的執行結果。狀態寄存器中的其他兩處定義bit7 – WPEN, bit[3:2] – BP[1:0]則主要與寫保護特性有關,它們的具體作用如下:

    2.4.2 廠商個性化

      除了6條事實標準的命令外,有些廠商還實現了一些自定義的命令,這些命令並不一定通用,一般用於較大容量(3byte地址碼,512Kb以上)的EEPROM上。痞子衡找了一款非常經典的EEPROM,來自Microchip的25AA系列(25AA1024),讓我們看看它有啥個性化的命令。這顆EEPROM容量為1Mb,屬於大容量EEPROM,為了提高EEPROM操作效率,Microchip為這顆EEPROM增加了Page/Sector/Chip Erase命令,使得擦除操作效率變高了,如果沒有這些個性化擦除命令,那麼只能通過標準WRITE命令去手動實現擦除操作,既麻煩又低效。

    2.5 SPI EEPROM數據速率

      數據存取速率是個重要的技術指標,咱們來看看SPI EEPROM的讀寫時序,前面痞子衡在講EEPROM分類的時候提到過EEPROM地址碼有1byte/2byte/3byte之分,地址碼的區別主要體現了EEPROM讀寫時序上。對於讀時序,在SPI總線發完READ(0x03)命令后,緊接着要發送想要讀取的內存地址,地址碼不同,發送的地址字節數也不同。對於容量大於512Kb的EEPROM(即地址碼為3byte),顯然要發送3byte的地址,才能確定要讀的數據所在地址,然後才能進行讀數據操作。

      而對於容量小於等於512Kb的EEPROM,關於1byte和2byte地址碼區分,有一個特殊的設計,即對於512byte容量的EEPROM,按容量來說其屬於2byte地址碼範疇,READ命令后需要發送2byte地址,但實際上只需要發送1byte地址(A7-A0),而最高地址位A8放在了READ命令碼bit3里,這樣可以節省1個字節的地址碼。因此1Kb – 512Kb容量的EEPROM地址碼為2byte,512byte及以下容量的EEPROM地址碼為1byte,如下圖所示:

      從上面讀時序可以看出,READ命令碼和地址碼發完之後幾乎沒有等待周期,就可以直接讀取EEPROM中數據,因此EEPROM讀數據速率完全取決於SPI總線速率,所以我們只需要打開EEPROM數據手冊,看看它最高能支持多高的SPI總線速率即可(常見的有2MHz/5MHz/10MHz/20MHz)。
      對於寫時序,就稍微複雜一些了,這裏不考慮地址碼區別,以2byte地址為例。首先在發送WRITE命令之前需要發送一個WREN命令使能寫操作,因為默認EEPROM在執行完上一次寫操作後會恢複寫禁止狀態,在發送WRITE命令進行寫操作之前必須保證EEPROM處於寫使能狀態。

      確保EEPROM進入寫使能狀態后,開始發送WRITE命令,然後是地址碼,接着是要寫入的數據,痞子衡前面講過Page在EEPROM是個結構概念,但其實也跟WRITE命令有關,因為EEPROM既可以按byte去寫,也可以按Page去寫,如果需要存入連續的數據,顯然按Page去寫效率比按Byte寫入更高。這裏需要注意的是,WRITE命令後面跟的字節數不能超過要寫入的首地址所在Page剩餘的字節數。下圖示例的Page寫時序最大byte數為16/32,是因為示例EEPROM的page size即16/32 byte。

      當一次WRITE時序內要寫入的數據全部發送完成之後,底下便進入等待周期,與READ時序不同的是,WRITE時序有等待周期,因為EEPROM內部要將緩存在page buffer里的數據編程到真正的內存空間里,這需要時間。用戶只能通過不斷地發送如下RDSR命令去讀取狀態寄存器bit0 – RDY#來判斷WRITE等待周期是否結束。因此寫時序速率不僅僅取決於SPI總線速率,還取決於等待周期時長。

      如果想快捷地了解SPI EEPROM的性能,最簡單的就是打開SPI EEPROM手冊,看首頁的feature介紹,如下是25AA080的簡要feature:

    • Max. Clock 10 MHz
    • 1024 x 8-bit Organization
    • 16 Byte Page (‘C’ version devices)
    • 32 Byte Page (‘D’ version devices)
    • Self-Timed Erase and Write Cycles (5 ms max.)
    • Block Write Protection:
      - Protect none, 1/4, 1/2 or all of array
    • Built-In Write Protection:
      - Power-on/off data protection circuitry
      - Write enable latch
      - Write-protect pin
    • Sequential Read
    • High Reliability:
      - Endurance: > 1M erase/write cycles
      - Data retention: > 200 years

    三、SPI EEPROM產品

      最後痞子衡收集了可以售賣SPI EEPROM芯片的廠商及產品系列:

    廠商 芯片系列 官方網址
    Microchip
    Atmel
    25AA, 25LC
    AT25
    ST M95
    Onsemi CAT25
    Renesas R1EX25
    Rohm BR25A, BR25G, BR25H, BR25S
    Fudan Micro FM25

      至此,EEPROM接口標準及SPI EEPROM痞子衡便介紹完畢了,掌聲在哪裡~~~

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

    【其他文章推薦】

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

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

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

    南投搬家前需注意的眉眉角角,別等搬了再說!

  • 玩轉VSCode-完整構建VSCode開發調試環境

    玩轉VSCode-完整構建VSCode開發調試環境

    隨着VSCode的不斷完善和強大,是時候將部分開發遷移到VS Code中了。

    目前使用VS2019開發.NET Core應用,一直有一個想法,在VS Code中復刻VS的開發環境,同時遷移到VS Code。

    那麼現在就開始吧。

    首先,安裝最新版的VS Code:,安裝完成后可能會提示升級,升級即可,升級后的版本信息:

    版本: 1.40.1 (system setup)
    提交: 8795a9889db74563ddd43eb0a897a2384129a619
    日期: 2019-11-13T16:49:35.976Z
    Electron: 6.1.2
    Chrome: 76.0.3809.146
    Node.js: 12.4.0
    V8: 7.6.303.31-electron.0
    OS: Windows_NT x64 10.0.16299

    接下來的操作分為幾個步驟:

    1. 安裝各種強大VS Code插件

    2. 創建.NET Core解決方案和工程

    3. 調試運行

    好的,那我們開始吧。

    一、安裝各種強大的VS Code插件

    1. C# extension for Visual Studio Code

    這個插件最重要的功能:

    • Lightweight development tools for .
    • Great C# editing support, including Syntax Highlighting, IntelliSense, Go to Definition, Find All References, etc.
    • Debugging support for .NET Core (CoreCLR). NOTE: Mono debugging is not supported. Desktop CLR debugging has .
    • Support for project.json and csproj projects on Windows, macOS and Linux.

    2. C# Extensions

    這個插件最有用的功能是可以右鍵新建C#類和C#接口,同時支持各種code snippets,例如 ctor 、prop等,具體功能特性,可以查看插件的說明。

     3. Auto-Using for C#

    這個插件自動添加using引用。

    4. vscode-solution-explorer

    這個插件給VS Code增加了解決方案tab, 支持新建解決方案、新建工程、添加引用、Nuget包,這個插件非常有用

    Adds a Solution Explorer panel where you can find a Visual Studio Solution File Explorer.

    • Can load any .sln version

    • Supports csproj, vcxproj, fsproj and vbproj (from vs2017 and before)

    • Supports dotnet core projects

    • You can create, delete, rename or move project folders and files.

    • You can create, delete, rename or move solution, solution folders and projects.

    • You can add or remove packages and references when the project is of kind CPS (dotnet core).

     

    5. Code Runner(韓俊老師出品,必屬精品)

    Run code snippet or code file for multiple languages: C, C++, Java, JavaScript, PHP, Python, Perl, Perl 6, Ruby, Go, Lua, Groovy, PowerShell, BAT/CMD, BASH/SH, F# Script, F# (.NET Core), C# Script, C# (.NET Core), VBScript, TypeScript, CoffeeScript, Scala, Swift, Julia, Crystal, OCaml Script, R, AppleScript, Elixir, Visual Basic .NET, Clojure, Haxe, Objective-C, Rust, Racket, Scheme, AutoHotkey, AutoIt, Kotlin, Dart, Free Pascal, Haskell, Nim, D, Lisp, Kit, and custom command

    即選中一段代碼,直接run

    6. vscode-icons

    通過這個插件,給各個文件和文件夾一個你更熟悉的圖標

    7. Visual Studio IntelliCode

    VS代碼智能提示,根據上下文語境,自動推薦你下一步用到的代碼,後台基於AI的

    8. NuGet Package Manager

    Nuget包管理,快速查詢定位Nuget包,並安裝。不過嘗試了一下午自定義Nuget源,沒搞定,估計是URL不對

    9. Docker

    10. Kubernetes

    其他的還需要配置GitHub、TFS類似的源代碼管理,TFS搞了兩個插件,都不好使,後續搞定后再更新一次。

     

    二、創建.NET Core解決方案和工程

    此時,VS Code的環境基本配置差不多了,接下來有兩種模式,創建解決方案和工程。

    1. 通過vscode-solution-explorer

    解決方案有了,很熟悉的感覺。

    我們可以繼續創建工程:右鍵sln,Add new project:

    此時會彈出工程模板,此時我們選擇ASP.NET Core Web API工程

    選擇C#

    然後繼續輸入工程名稱:例如 TestWebApi

    熟悉的感覺來了。此時就可以開始coding了。

    以上是我們通過vscode-solution-explorer新建解決方案和工程。同時我們可以通過命令行來搞定。

    2. 通過Dotnet CLI命令行

    新建sln:

    dotnet "new" "sln" "-n" "EricTest" "-o" "e:\Work\ServiceDependency"

    新建ASP.NET Core WebAPI工程

    dotnet "new" "webapi" "-lang" "C#" "-n" "TestWebApi" "-o" "TestWebApi"

    將TestWebApi工程添加到解決方案EricTest

    dotnet "sln" "e:\Work\ServiceDependency\EricTest.sln" "add" "e:\Work\ServiceDependency\TestWebApi\TestWebApi.csproj"

    三、調試運行

    在Debug選項卡中新增調試配置,重點設置要調試的program

    保存后,啟動調試:

     

    程序中增加斷點,然後

    輸入URL:https://localhost:5001/WeatherForecast

     既可以調試了。

     

    以上是今天集中配置VS Code開發調試環境的總結,分享給大家。

     

    周國慶

    2019//11/16

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

    【其他文章推薦】

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

    網頁設計一頭霧水??該從何著手呢? 找到專業技術的網頁設計公司,幫您輕鬆架站!

    ※想知道最厲害的台北網頁設計公司推薦台中網頁設計公司推薦專業設計師”嚨底家”!!