標籤: USB CONNECTOR

  • Docker學習(三)-簡單的私有DockerHub搭建

    Docker學習(三)-簡單的私有DockerHub搭建

    Docker Hub

    目前Docker官方維護了一個公共倉庫https://hub.docker.com, 其中已經包括100000+個的鏡像。大部分需求都可以通過在 Docker hub中直接下載鏡像來實現,

    註冊登錄

    可以在 免費註冊一個Docker賬號。在命令行執行docker login輸入用戶名及密碼來完成在命令行界面登記Docker Hub。你可以通過docker logout退出登錄。

    docker login

     

    拉取鏡像

    可以通過docker search命令來查找官方倉庫中的鏡像,並利用docker pull命令來將它下載到本地。

     

    推送鏡像

    用戶也可以在登錄后通過docker push命令來將自己的鏡像推送到Docker Hub。

    docker pull tomcat

     docker images

    修改本地鏡像的名字為賬號名/鏡像名

    上傳鏡像到公共倉庫

    docker push woxpp/tomcat-test:latest

    登錄界面查看

    docker pull woxpp/tomcat-test

     

    私有倉庫

    有時候使用Docker Hub這樣的公共倉庫可能不方便,用戶可以創建一個本地倉庫供私人使用。比如,基於公司內部項目構建的鏡像。
    docker-registry是官方提供的工具,可以用於構建私有的鏡像倉庫。

    安裝運行docker-registry

    可以通過獲取官方registry鏡像來運行。默認情況下,倉庫會被創建在容器的/var/lib/registry目錄下。可以通過-v參數來將鏡像文件存放在本地的指定路徑。

    docker run --name registry -d  -p 5000:5000 --restart=always  -v /opt/registry:/var/lib/registry registry
    docker ps -a

    測試是否成功

    使用docker tag將session-web:latest這個鏡像標記為192.168.50.24:5000/session-web:latest格式為docker tag IMAGE:TAG/]REPOSITORY[:TAG]

    docker tag docker.io/tomcat 192.168.50.24:5000/tomcat-2:latest
    

    使用docker push上傳標記的鏡像

    docker push 192.168.50.24:5000/tomcat-2:latest

    驗證上傳的鏡像

     

     

     先刪除已有鏡像,再嘗試從私有倉庫中下載這個鏡像。

    docker images
     docker rmi 192.168.50.24:5000/tomcat-2
    docker pull 192.168.50.24:5000/tomcat-2 

     

    注意事項

    The push refers to a repository [192.168.50.24:5000/consul]
    Get https://192.168.50.24:5000/v1/_ping: http: server gave HTTP response to HTTPS client

    可以用下面方式解決

    修改客戶端/etc/docker/daemon.json中寫入如下內容

    {
        "registry-mirror":[
            "http://hub-mirror.c.163.com"
        ],
        "insecure-registries":[
            "192.168.50.24:5000"
        ]
    }

    重新啟動docker后再試試
    service docker restart

     

     

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

    【其他文章推薦】

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

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

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

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

  • Windows終端利器Cmder

    Windows終端利器Cmder

    在IT這一行,大部分情況下都是推薦大家使用Linux或者類Unix操作系統去編程,Linux作為一代優秀的操作系統,已經人盡皆知,在IT行業已經成為核心。有條件的大佬都選擇了使用mac編程,最優秀的莫過於終端體驗了,與Linux完全一致的命令行,帶來了許許多多的方便,但是使用Windows的用戶呢?相信大家都使用過cmd終端,它到底好不好呢。相信大家心中已經有了評判。

    一、為什麼要換成cmder

    現在我就要推薦一款Windows下的終端—>cmder
    先來上兩張圖給大家看看

    都不用我說,一眼就能分辨出他倆的區別了,其實他倆最大的區別是cmder完全支持Linux命令行,包括vi,而且可以多開,快捷鍵複製粘貼,分屏等,功能非常強大

    二、下載和安裝

    1.下載

    官網自己下載也可以

    • 在官網下載的時候有兩個版本
      • Mini版本,只有簡單的命令行
      • Full版本,包含git功能(分佈式版本控制系統的git)

    我推薦大家安裝Full版本,這樣就可以不用單獨安裝git了

    2.安裝

    安裝非常簡單,下載完成后,直接解壓到你存放軟件的目錄就好了

    然後雙擊一下cmder.exe就可以先簡單體驗一下了

    三、個性化設置

    這款軟件可以完全替代Windows系統自帶的cmd終端,當然需要一點人性化的設置

    1.配置環境變量

    我就只上圖了,環境變量配置太過簡單了,百度上太多了,都是通用套路,配置完環境變量,就可以直接在Windows+r鍵里運行cmder打開終端了

    上圖中我把git也配置進去了,這樣就不會說git不是內部或者外部命令了

    2.配置右鍵菜單啟動

    右鍵管理員身份運行cmder.exe,然後把下面的命令複製到cmder中執行一次

    // 設置任意地方鼠標右鍵啟動Cmder
    Cmder.exe /REGISTER ALL

    3.進入設置的方法

    右下角的,然後選擇Settings或者直接使用快捷鍵Windows+Alt+p打開設置

    如果不習慣英文,可以將設置改成中文

    下次再次打開設置,又會中文,只有這個設置生效一次,其他的都可以永久生效

    4.設置字體風格等

    設置字體的風格,大小等,圖中紅色位置不要勾選,否則會出現cmder終端字體重疊錯位的問題

    終端界面的字體大小在設置里可以修改,也可以在終端界面滑動鼠標滾輪,或者觸控板雙擊縮放調整字體大小

    5.窗口位置大小記憶

    勾選這兩個設置,只需要設置一次,下次會自動記住上次終端在桌面出現的位置和窗口大小

    6.設置vi模式下ESC鍵最小化窗口的問題

    • 將圖中紅色改成除了總是的其他選項,否則使用vi時會出現無法切換模式的問題
    • 勾選綠色的選項可以解決打開多個終端,任務欄显示多個窗口的問題

    7.解決中文亂碼的問題

    在使用ls命令時,中文亂碼的解決方案,將下面的代碼複製到圖中位置

    set LANG=zh_CN.UTF-8
    set LC_ALL=zh_CN.utf8

    8.強製作為默認終端

    • 圖中綠色設置可以強制將cmder註冊成Windows的默認終端

      設置此選項后,系統啟動后就會生效,且,即使你打開的是cmd,也會被放到cmder的窗口中執行

    • 紅色選項可以解決每次關閉控制台時,彈出確認關閉的彈窗

    9.解決粘貼多行文本時的彈窗

    例如在終端中執行多行SQL語句,總會彈出提示,勾選選項可以解決

    10.將命令提示改成$

    默認的命令提示符是λ,大家都知道Linux是$,這裏提供一下修改的方法,並不是必須的

    1)首先在cmder的安裝目錄下,找到vendor/目錄,然後找到clink.lua文件

    2)右鍵使用sublime打開

    • 沒有sublime或者notepad++打開也可以,還沒有的話,記事本也可以的

    3)打開后可以Ctrl+F查找下面的字段
    local lambda =
    4)將local lambda =""的值替換成$

    5)保存關閉,重啟終端

    11.將Idea的Terminal終端換成cmder

    1)在idea中打開其他設置界面,如圖所示

    在idea中settings是對當前項目生效,Other Settings是對所有項目生效

    2)如圖中修改shell Path的路徑,替換成下面的內容

    注意將cmder安裝目錄換成你的安裝目錄

    //這種方式比較可靠,避免了環境變量失效的問題
    "cmd.exe" /k ""你的cmder安裝目錄\vendor\init.bat""
    
    //或者,這個需要有環境變量
    "cmd.exe" /k ""%環境變量配置的cmder home目錄名稱%\vendor\init.bat""

    3)再次打開Terminal終端就可以使用Linux命令了

    12.將vscode的Terminal終端設置成cmder

    1)打開設置

    2)搜索code save,點擊打開設置json文件

    3)將下面的代碼粘貼到文件中,修改為自己需要的內容

    注意修改cmder的安裝目錄為自己的安裝目錄

    // 設置終端為cmder
    "terminal.integrated.shell.windows": "cmd.exe",
    "terminal.integrated.env.windows": {
        //設置cmder的根目錄
        "CMDER_ROOT": "cmder的根目錄"
    },
    "terminal.integrated.shellArgs.windows": [
        "/k",
        //設置啟動初始化目錄
        "cmder的根目錄\\vendor\\init.bat"
    ],
    
    //下面的設置可以不需要
    //終端顏色配置
    "workbench.colorCustomizations": {
        //可以將鼠標放到下面的色號上根據自己的偏好進行選擇
        "terminal.foreground": "#37FF13",
        "terminal.background": "#2b2424"
    },
    "terminal.integrated.cursorBlinking": true,
    //設置terminal中的行高
    "terminal.integrated.lineHeight": 1.1,
    "terminal.integrated.letterSpacing": 0.1,
    "terminal.integrated.fontSize": 12, //字體大小設置
    "terminal.integrated.fontFamily": "monaco", //字體設置
    "terminal.integrated.shell.linux": "/bin/zsh"

    4)Ctrl+J打開終端,就可以使用了

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

    【其他文章推薦】

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

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

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

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

  • 農地轉用的特殊案例──北海道知內町太陽能發電廠(上)

    文:宋瑞文(加州能源特約撰述)

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

    【其他文章推薦】

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

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

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

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

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

  • 西班牙東北部化學工廠爆炸 釀1死6傷

    摘錄自2020年1月15日中央社報導

    西班牙東北部發生化學工廠爆炸事故,造成一人喪命,傷及六人。當地媒體引述消防人員的說法表示,爆炸很有可能是化學意外所引起。

    「先鋒報」(La Vanguardia)和「國家報」(ElPais)等媒體在網站上表示,這起在塔拉戈納省(Tarragona)發生的爆炸引發衝擊波,造成一棟建築物坍塌,一人身亡。

    加泰隆尼亞救災服務處發言人證實,附近有建築物倒塌並有一人喪生,但還無法確定大樓倒塌與爆炸或大火有關。

    民防局建議附近民眾待在室內,並預防性緊鎖門窗,但說:「沒有證據顯示(爆炸)產生有毒的煙霾。」

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

    【其他文章推薦】

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

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

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

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

  • 印尼水患災情慘重 雅加達省長遭民眾控告

    摘錄自2020年1月14日中央社報導

    印尼一名律師今天(14日)表示,在暴雨引發洪水及土石流災情,導致數十人喪命、數千人無家可歸後,雅加達省長阿尼斯(AniesBaswedan)因此被這座大城市的居民控告。

    超過200名水患受災民眾昨天在首都雅加達(Jakarta)地方法院提出集體訴訟,尋求總計約430億印尼盾(約新台幣9000萬元)的賠償金。

    這起訴訟指出,阿尼斯未能替雅加達這座大型城市提供合適的預警系統及有效的緊急救難措施,好讓人民的性命及財務損失降到最低。

    雅加達的法務局沒有立即回應置評請求。

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

    【其他文章推薦】

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

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

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

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

  • 2016中國國際新能源汽車峰會

    2016中國國際新能源汽車峰會

    2016中國國際新能源汽車峰會將于明年3月在北京召開

    隨著化石能源、石油資源的日益枯竭,大氣污染和溫室氣體的排放,加之傳統內燃機驅動汽車的能源利用率很低,新能源汽車已成為未來發展的必然趨勢。

    新能源汽車是我國戰略性新興產業之一,也是我國應對氣候變化、保障能源安全、減少溫室氣體排放、防治城市空氣污染的重要途徑之一。近10年來,我國把新能源汽車作為未來汽車的主要發展方向,從國家層面給予了極大的關注和支持。去年,我國新能源汽車產銷量較上年增長了三倍,這種爆發式增長,是國家對於新能源汽車不斷加大政策扶持的結果。

    在這一市場背景下,2016中國國際新能源汽車峰會將立足於中國新能源汽車行業的實際情況,進一步解析業內人士比較關心的政策法規和最新的技術動向以及未來的發展趨勢,深入探討電控集成系統、無線充電技術以及新能源汽車切入能源互聯網的契機等熱點話題。這裡還將是一個您與政府高層、OEM製造商、行業領袖和專家進行跨國項目交流的最佳平臺。

    會議亮點:
    •    十三五新能源汽車發展規劃
    •    充電新標準出臺和實施時間
    •    新能源汽車產業的全球市場戰略
    •    探索未來電池新材料技術
    •    三元鋰電池最新技術
    •    驅動電機的效率提升和性能優化
    •    電池管理系統如何提高整包級別的安全性
    •    電機控制器如何改善電機運行效率並降低能耗
    •    整車控制器的關鍵技術
    •    充電樁技術和網路建設
    •    無線充電技術的巨大市場前景
    •    插電式混合動力的技術和市場
    •    電動汽車電氣系統的設計與優化
    •    燃料電池汽車未來的商業化路徑
    •    新能源商用車市場剖析和關鍵技術
    •    開放技術專利能否推動新能源汽車行業加速發展
    •    互聯網如何推動新能源汽車產業升級
    •    新能源汽車切入能源互聯網的契機
    •    與傳統汽車租賃公司的合作模式
    •    金融租賃如何解圍新能源汽車的商業模式困局

    請聯繫:
    Lucy Shi 石小姐
    電話: +86 21- 33191337-623
    手機:+86 13166042312
    郵箱:
    會議網址:

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

    【其他文章推薦】

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

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

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

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

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

  • 福建物價局:電動汽車充電服務費1.2元/度為上限

    據福建省物價局最新批復,電動汽車充電服務費實行政府指導價管理,充電服務費標準(不含電費)上限按1.2元/度收取,下浮不限。   理論上來說,給電動汽車充電採取“充電服務費+電費”的繳費方式。充電電費方面,分兩種情況

    1. 集中接入電網的充電樁,高峰時段0.9139元/度,低谷時段0.3305元/度,其餘時段0.6222元/度。
    2. 分散接入電網的充電樁,居民家庭住宅、居民住宅社區的充電設施收0.533元/度;到黨政機關、企事業單位和社會公共停車場中設置的充電設施用電高峰時段收1.15975元/度,低谷時段收0.41445元/度,其餘時段收0.7871元/度。

    據悉,相比於汽油、天然氣,用電的成本更低。據業內人士統計,在廈門,計程車司機用油每公里成本在0.6元-0.7元,用氣每公里成本約在0.4元,而用電每公里成本在0.3元。目前,廈門新建的充電樁設備只有計程車可充電,未對社會車輛開放。運管處相關人士透露,他們上月報備的充電服務費為0.6元/度。   而對於從事電動汽車充換電設施服務的經營性企業來說,2020年前免收基本電費。

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

    【其他文章推薦】

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

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

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

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

  • 富士康杭州投12億,發展新能源汽車租賃業務

    富士康集團總投資12億元,註冊資本1億元,成立杭州浙譽新能源汽車服務有限公司。作為富士康科技集團在杭州開展新能源汽車分時租賃運營的服務主體,專案計畫三年內在杭州地區累計投放5000輛電動汽車。   電動汽車分時租賃是一種城市短途出行方式,在汽車共用的基礎上使用電動汽車進行共用運營,通過會員制的方式以小時計費的新能源電動汽車的租賃服務。其租賃模式就像“租公共自行車一樣”,會員通過網路或手機終端輕鬆實現汽車預定,然後線上下取車實現消費,整個過程全程自助。   該專案是2015年3月富士康集團與杭州市政府簽署全面戰略合作協議後,與杭州進行全面深化合作所邁出的實質性第一步。

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

    【其他文章推薦】

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

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

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

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

  • 利用爬蟲爬取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 是電子產業重要的元件?

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

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

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