跳到主要內容

發表文章

目前顯示的是 10月, 2020的文章

菜渣開源一個基於 EMIT 的 AOP 庫(.NET Core)

目錄 1,快速入門 1.1 繼承 ActionAttribute 特性 1.2 標記代理類型 2,如何創建代理類型 2.1 通過API直接創建 2,創建代理類型 通過API 通過 Microsoft.Extensions.DependencyInjection 通過 Autofac 3,深入使用 代理類型 方法、屬性代理 上下文 攔截方法或屬性的參數 非侵入式代理 Nuget 庫地址:https://www.nuget.org/packages/CZGL.AOP/ Github 庫地址:https://github.com/whuanle/CZGL.AOP CZGL.AOP 是 基於 EMIT 編寫的 一個簡單輕量的AOP框架,支持非侵入式代理,支持.NET Core/ASP.NET Core,以及支持多種依賴注入框架。 1,快速入門 CZGL.AOP 使用比較簡單,你只需要使用 [Interceptor] 特性標記需要代理的類型,然後使用繼承 ActionAttribute 的特性標記要被代理的方法或屬性。 1.1 繼承 ActionAttribute 特性 ActionAttribute 是用於代理方法或屬性的特性標記,不能直接使用,需要繼承后重寫方法。 示例如下: public class LogAttribute : ActionAttribute { public override void Before(AspectContext context) { Console.WriteLine("執行前"); } public override object After(AspectContext context) { Console.WriteLine(...

Java併發編程(05):悲觀鎖和樂觀鎖機制

本文源碼:GitHub·點這裏 || GitEE·點這裏 一、資源和加鎖 1、場景描述 多線程併發訪問同一個資源問題,假如線程A獲取變量之後修改變量值,線程C在此時也獲取變量值並且修改,兩個線程同時併發處理一個變量,就會導致併發問題。 這種并行處理數據庫的情況在實際的業務開發中很常見,兩個線程先後修改數據庫的值,導致數據有問題,該問題復現的概率不大,處理的時候需要對整個模塊體系有概念,才能容易定位問題。 2、演示案例 public class LockThread01 { public static void main(String[] args) { CountAdd countAdd = new CountAdd() ; AddThread01 addThread01 = new AddThread01(countAdd) ; addThread01.start(); AddThread02 varThread02 = new AddThread02(countAdd) ; varThread02.start(); } } class AddThread01 extends Thread { private CountAdd countAdd ; public AddThread01 (CountAdd countAdd){ this.countAdd = countAdd ; } @Override public void run() { countAdd.countAdd(30); } } class AddThread02 extends Thread { private CountAdd countAdd ; public AddThread02 (CountAdd countAdd){ this.countAdd = countAdd ; } @Override public void run() { countAdd.cou...

文本挖掘之情感分析(一)

一、文本挖掘        文本挖掘則是對文本進行處理,從中挖掘出來文本中有用的信息和關鍵的規則,在文本挖掘領域應用最往廣泛的是對文本進行分類和聚類,其挖掘的方法分為無監督學習和監督學習。文本挖掘還可以劃分為7大類:關鍵詞提取、文本摘要、文本主題模型、文本聚類、文本分類、觀點提取、情感分析。     關鍵詞提取 :對長文本的內容進行分析,輸出能夠反映文本關鍵信息的關鍵詞。    文本摘要 :許多文本挖掘應用程序需要總結文本文檔,以便對大型文檔或某一主題的文檔集合做出簡要概述。    文本聚類 :主要是對未標註的文本進行標註,常見的有 K均值聚類和層次聚類。    文本分類 :文本分類使用監督學習的方法,以對未知數據的分類進行預測的機器學習方法。    文本主題模型 LDA :LDA(Latent Dirichlet Allocation)是一種文檔主題生成模型,也稱為一個三層貝恭弘=叶 恭弘斯概率模型,包含詞、主題和文檔三層結構,該模型可以用於獲取語料的主題提取和對不同類別的文檔進行分類。    觀點抽取 :對文本(主要針對評論)進行分析,抽取出核心觀點,並判斷極性(正負面),主要用於電商、美食、酒店、汽車等評論進行分析。    情感分析 :對文本進行情感傾向判斷,將文本情感分為正向、負向、中性。用於口碑分析、話題監控、輿情分析。    因為自己的論文寫的是關於情感分析方面的內容,因此打算接下來主要寫情感分析系列的內容,今天主要寫關於情感分析的介紹以及發展史。 二、情感分析 1. 含義      情感分析主要是通過分析人們對於服務、產品、事件、話題來挖掘出說話人/作者觀點、情感、情緒等的研究。情感分析按照研究內容的不同,可以分為:意見挖掘 / 意見提取 / 主觀性分析 / 情感傾向分析、情感情緒分析、情感打分等。情感傾向問題,即是指挖掘出一段語料中說話人/作者對於某一話題/事件所持有的態度,如褒義、貶義、中性、兩者兼有。情感情緒,則是將情感傾向進行更進一步的細化,依據"大連理工大學的情...

服務設計思考:平台化

平台是一套完整的服務。也是一套內部自洽的系統。核心在於 分離 ,業務與通用服務隔離,業務與通用功能隔離。 目標: 對需求方: 快速響應。可以敏捷地進行需求迭代。 對第三方業務方: 以產品的方式提供服務。所見即所得。所有功能對業務方透明。 對測試方: 簡易明了的測試方式。利於自動化測試,灰度測試。 對運維方: 持續集成,自動化編排,自動化部署。 數據方: 提供多維度,詳盡的服務數據。可以給數據方提供簡便的數據分析。 內部開發: 敏捷開發。迅速集成。 實現: 如何實現需求的快速響應? 明確的方向,清晰的邊界。確認通用語言,核心領域。敏捷開發,快速迭代。AB 測試。 如何為第三方提供產品式的服務? 所見即所得。詳盡的文檔。第三方調試平台,第三方管理平台。 mock 服務,自動化測試,swagger 文檔。 Devops,CI,DI 等持續集成,服務監控。 業務數據與分析數據異構存儲。提供易於分析的數據服務。 組內服務負責制度,人類最佳的合作人數是 2-3 人。所以兩人維護一個項目,一人主導,一人輔助,兩人交叉合作是一個很好的團隊合作模式。如圖形成一個網狀模式(紅色線代表主導,黑色線輔助)。這樣每一個項目都將有兩個熟悉的人。 原則 單一職責。 業務關注業務,功能關注功能。 確認邊界,確認核心領域。 所見即所得。 實施 如何推進業務開發快速響應? 抽離變化與不變。形成基礎服務 如下面一套用戶體系,將服務抽離,將變與不變隔離。 用戶 api: 主要提供用戶相關的接口,變化大,更偏向於業務; 用戶中心: 主要管理用戶核心領域,變動不大,需穩定高可用的服務; 鑒權授權中心: 變動不大,主要管理用戶憑證核心領域; 抽離通用功能。 那些非業務的通用功能應隔離於業務之外: 組件化 , 工具化 , 服務化 。 如 來源監控 , 接口限流 , 日誌分析 , 應用監控 , 服務依賴 , 配置管理 , 系統部署 等(業務人員不必關心這些功能相關的事情,只需要關注於具體的業務領域)。關注點分離。 如上面所涉及的,從 Spring C...

Java多線程與併發基礎面試題

CS-LogN思維導圖:記錄專業基礎 面試題 開源地址:https://github.com/FISHers6/CS-LogN 多線程與併發基礎 實現多線程 面試題1:有幾種實現線程的方法,分別是什麼 1.繼承Thread類,啟動線程的唯一方法就是通過 Thread 類的 start()實例方法,start()方法是一個 native 方法,它將啟動一個新線程去執行 run()方法 2.實現 Runnable 接口,重寫run()函數,作為參數放到Thread類構造函數中作為target屬性,運行start()方法 線程池創建線程、Callable本質還是使Runnable創建,Callable是父輩類繼承了Runnable,線程池需傳入參數 面試題2:實現Runnable方法好,還是繼承Thread類好 實現Runnable接口更好 1.單一繼承原則,如果繼承了Thread,就不能繼承其它類了,限制了可擴展性 2.Thread類每次只能創建一個獨立的線程,損耗大,而Runnable能利用線程池工具來創建線程 3.從代碼架構上看,run內容應該與Trhead代碼解耦 面試題3:一個線程兩次調用start方法會出現什麼情況(考察源碼) 第二次會出現異常,從start源碼上和線程生命周期上分析,一個線程start后, 改變了threadState狀態字;而第二次再start每次會先檢查這個狀態不是0就報異常 面試題4:既然start方法會調用run方法,為什麼我們還是要用start方法,而不是直接調用run方法呢(考察源碼) 因為start后線程才會經過完整的線程生命周期,start調用native start0,虛擬機執startThread,thread_entry入口中調用Thread的run, 面試題5:start和run有什麼區別 run()方法:只是普通的方法,調用run普通方法,可以重複多次調用 start()方法,會啟動一個線程,使得虛擬機去調用Runnable對象的run()方法,不能多次啟動同一個線程 面試題6:start方法如...

關於 JOIN 耐心總結,學不會你打我系列

現在隨着各種數據庫框架的盛行,在提高效率的同時也讓我們忽略了很多底層的連接過程,這篇文章是對 SQL 連接過程梳理,並涉及到了現在常用的 SQL 標準。 其實標準就是在不同的時間,制定的一些寫法或規範。 從 SQL 標準說起 在編寫 SQL 語句前,需要先了解在不同版本的規範,因為隨着版本的變化,在具體編寫 SQL 時會有所不同。對於 SQL 來說,SQL92 和 SQL99 是最常見的兩個 SQL 標準,92 和 99 對應其提出的年份。除此之外,還存在 SQL86、SQL89、SQL2003、SQL2008、SQL2011,SQL2016等等。 但對我們來說,SQL92 和 SQL99 是最常用的兩個標準,主要學習這兩個就可以了。 為了演示方便,現在數據庫中加入如下三張表: 每個學生屬於一個班級,通過班級的人數來對應班級的類型。 -- ---------------------------- DROP TABLE IF EXISTS `Student`; CREATE TABLE `Student` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(20) NOT NULL DEFAULT '', `birth` varchar(20) NOT NULL DEFAULT '', `sex` varchar(10) NOT NULL DEFAULT '', `class_id` int(11) NOT NULL COMMENT '班級ID', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of Student -- ---------------------------- INSERT INTO `Student` VALUES ('1', '胡一', '1994.1.1', '男', '1...

【K8S】Service服務詳解,看這一篇就夠了!!

k8s用命名空間 namespace 把資源進行隔離,默認情況下,相同的命名空間里的服務可以相互通訊,反之進行隔離。 1.1 Service Kubernetes中一個應用服務會有一個或多個實例(Pod,Pod可以通過rs進行多複本的建立),每個實例(Pod)的IP地址由網絡插件動態隨機分配(Pod重啟后IP地址會改變)。為屏蔽這些後端實例的動態變化和對多實例的負載均衡,引入了Service這個資源對象,如下所示: apiVersion: v1 kind: Service metadata: name: nginx-svc labels: app: nginx spec: type: ClusterIP ports: - port: 80 targetPort: 80 selector: #service通過selector和pod建立關聯 app: nginx 根據創建Service的type類型不同,可分成4種模式: ClusterIP : 默認方式。根據是否生成ClusterIP又可分為普通Service和Headless Service兩類: 普通Service:通過為Kubernetes的Service分配一個集群內部可訪問的 固定虛擬IP (Cluster IP),實現集群內的訪問。為最常見的方式。 Headless Service:該服務不會分配Cluster IP,也不通過kube-proxy做反向代理和負載均衡。而是通過DNS提供穩定的絡ID來訪問,DNS會將headless service的後端直接解析為podIP列表。主要供StatefulSet使用。 NodePort :除了使用Cluster IP之外,還通過將service的port映射到集群內每個節點的相同一個端口,實現通過nodeIP:nodePort從 集群外訪問服 務。 LoadBalancer :和nodePort類似,不過除了使用一個Cluster IP和nodePort之外,還會向所使用的公有雲申請一個負載均衡器(負載均衡器後端映射到各節點的nodePort),實現從集群外通過LB訪問服務。 ExternalN...

龍芯團隊完成CoreCLR MIPS64移植,已在github開源

國產龍芯的軟件生態之中.NET不會缺席,畢竟 C# 與 .NetCore/Mono 也是全球幾大主流的編程語言和運行平台之一,最近一段時間聽到太多的鼓吹政務領域不支持.NET, 大家都明白這是某些人為了自己的利益打壓使用.NET技術的公司,我今天寫這篇文章就是想通過龍芯團隊的行動告訴更多人一起來推動.NET技術在中國的發展。希望龍芯廠商、支持龍芯的國產操作系統廠商能高度重視這個問題,主動加入 .Net Core 社區,加入.NET基金會,积極貢獻代碼,儘快做好適配工作。 龍芯團隊一直在做net core的mips64移植工作,2020年6月18日完成了里程碑性的工作,在.NET Core 3.1分支上完成了MIPS64 的移植工作,目前已經在github上開源,開源地址:https://github.com/gsvm/coreclr 。具體說明可以參見 https://github.com/dotnet/runtime/issues/38069。 龍芯團隊正在做移植后的測試工作,已經完成了 9500 多項測試,ASP.NET Core示例程序 FlightFinder 已經可以在MIPS64 上正常運行,具體可以參看 https://github.com/dotnet/runtime/issues/4234。 龍芯團隊還在github上面為龍芯.NET 建立了一個倉庫 https://github.com/gsvm/loongson-dotnet,用於關於龍芯的.NET信息,工作和下載,開源協議採用和.NET Core一樣的MIT協議。 根據這個倉庫的信息,龍芯團隊將在不久的將來發布.NET Core 3.1版本,然後升級到https://github.com/dotnet/runtime ,也就是.NET 5了。目前這項工作正在緊鑼密鼓的進行,非常歡迎大家的積极參与貢獻,包括issue或者PR,如果您有任何問題或需要任何支持,請隨時提交問題或通過电子郵件:aoqi@loongson.cn 與龍芯團隊聯繫。 在文章的最後,我向你分享一個龍芯團隊成員 xiangzhai 在這個 https://github.com/xiangzhai/mono/issues/2 提到了指令集相關的編程的一些相關知識: OpenJDK、CorelCLR、mo...

如何提升自己?

如何提升自己? 看完後浪,感慨良多... 在程序員圈子,聽得最多的便是"35歲中年危機"。 危機 其實不僅僅存在"35歲危機",還有"畢業危機","被裁員危機",不僅僅在程序員圈子,幾乎所有圈子都是這樣,就像剛畢業的大學生說的:畢業等於失業。現在的社會飛速發展,我們常常感嘆大多數父母一代的人,智能手機玩着都比較費勁,其實也算是一種危機。其實不管任何職業,任何年齡的人,都應該保持"學習"的狀態,只有自身有了底氣,才能挺直了腰板,度過一個又一個危機。恩,做的不開心,我就換個工作...厲害的人,都是別人來請他去上班的。 作為一個Javaer,當然也需要不斷的保持學習,特別是對於剛畢業的人,可能在找第一份工作的時候,你大廠與你擦肩而過,但是只要你對未來有一個完整的規劃,3年後,你一樣能達到你的目標。 說了這麼多,只是為了強調學習的重要性。但是如何學習?學習什麼?這才是真正的問題。 如何學習? 很多人喜歡看視頻學習,記得剛學 Java 的時候,很多同學都會去看馬士兵,傳智博客等等。。。的確,視頻適合帶你入門,但是卻不適合進階。 如果你是一個什麼都不知道的小白, 不知道什麼是IDE,是什麼叫配置環境變量,那麼的確可以看看視頻學習,因為它能帶你很快的上手,避免走很多坑。 但是如果你是一個有一點項目經驗的人,那麼個人是不推薦通過視頻來學習新的知識的。第一個便是因為資源太少。除了培訓機構和各種專門為了做教育行業的人,很少有其他人會專門通過視頻介紹技術,即使有,視頻質量也難以得到保障。第二個便是效率問題,看視頻你不敢跳過,害怕錯過知識點,你也更加容易走神,因為進度掌握在別人手裡。 所以最好的學習方式便是看資料,比如看書,看官方文檔等。 如何看書? 書讀百遍,其義自見。能真正把一本書看很多遍的人,一定能體會到這句話的精髓所在。 擁有不同知識的人,看一本書的收貨一定是不一樣的。這裏可以簡單舉一個例子:一個剛學完 Java 基礎知識的人,看《Effective Java》的時候,可能只會死記硬背。一個擁有三年開發經驗的人,看《Effectice Java》的時候,會覺得恍然大悟。而一個擁有豐富的開發經驗的人,看《Effective Jav...

從 0 開始機器學習 - 神經網絡反向 BP 算法!

最近一個月項目好忙,終於擠出時間把這篇 BP 算法基本思想寫完了,公式的推導放到下一篇講吧。 一、神經網絡的代價函數 神經網絡可以看做是複雜邏輯回歸的組合,因此與其類似,我們訓練神經網絡也要定義代價函數,之後再使用梯度下降法來最小化代價函數,以此來訓練最優的權重矩陣。 1.1 從邏輯回歸出發 我們從經典的邏輯回歸代價函數引出,先來複習下: \[J(\theta) = \frac{1}{m}\sum\limits_{i = 1}^{m}{[-{y^{(i)}}\log ({h_\theta}({x^{(i)}}))-( 1-{y^{(i)}})\log ( 1 - h_\theta({x^{(i)}}))]} + \frac{\lambda}{2m} \sum\limits_{j=1}^{n}{\theta_j^2} \] 邏輯回歸代價函數計算每個樣本的輸入與輸出的誤差,然後累加起來除以樣本數,再加上正則化項,這個我之前的博客已經寫過了: 從 0 開始機器學習 - 邏輯回歸原理與實戰! 從 0 開始機器學習 - 正則化技術原理與編程! 這裏補充一點對單變量邏輯回歸代價函數的理解,雖然這一行代價公式很長: \[cost(i) = -{y^{(i)}}\log ({h_\theta}({x^{(i)}}))-( 1-{y^{(i)}})\log ( 1 - h_\theta({x^{(i)}})) \] 但是其實可以把它簡單的理解為輸出與輸入的方差,雖然形式上差別很大,但是可以幫助我們理解上面這個公式到底在計算什麼,就是計算輸出與輸入的方差,這樣理解就可以: \[cost(i) = h_{\theta}(x^{(i)} - y^{(i)})^2 \] 1.2 一步步寫出神經網絡代價函數 前面講的簡單邏輯回歸的只有一個輸出變量,但是在神經網絡中輸出層可以有多個神經元,所以可以有很多種的輸出,比如 K 分類問題,神經元的輸出是一個 K 維的向量: 因此我們需要對每個維度計算預測輸出與真實標籤值的誤差,即對 K 個維度的誤差做一次求和: \[\sum\limits_{i = 1}^{k}{[-{y_k^{(i)}}\log ({h_\theta}({x^{(i)}}))_k-( 1-{...

C#中的閉包和意想不到的坑

雖然閉包主要是函數式編程的玩意兒,而C#的最主要特徵是面向對象,但是利用委託或lambda表達式,C#也可以寫出具有函數式編程風味的代碼。同樣的,使用委託或者lambda表達式,也可以在C#中使用閉包。 根據WIKI的定義,閉包又稱語法閉包或函數閉包,是在函數式編程語言中實現語法綁定的一種技術。閉包在實現上是一個結構體,它存儲了一個函數(通常是其入口地址)和一個關聯的環境(相當於一個符號查找表)。閉包也可以延遲變量的生存周期。 嗯。。看定義好像有點迷糊,讓我們看看下面的例子吧 class Program { static Action CreateGreeting(string message) { return () => { Console.WriteLine("Hello " + message); }; } static void Main() { Action action = CreateGreeting("DeathArthas"); action(); } } 這個例子非常簡單,用lambda表達式創建一個Action對象,之後再調用這個Action對象。 但是仔細觀察會發現,當Action對象被調用的時候, CreateGreeting 方法已經返回了,作為它的實參的message應該已經被銷毀了,那麼為什麼我們在調用Action對象的時候,還是能夠得到正確的結果呢?   原來奧秘就在於,這裏形成了閉包。雖然CreateGreeting已經返回了,但是它的局部變量被返回的lambda表達式所捕獲,延遲了其生命周期。怎麼樣,這樣再回頭看閉包定義,是不是更清楚了一些?   閉包就是這麼簡單,其實我們經常都在使用,只是有時候我們都不自知而已。比如大家肯定都寫過類似下面的代碼。 void AddControlClickLogger(Control control, string message) { control.Click += delegate ...

Thunk函數的使用

Thunk函數的使用 編譯器的求值策略通常分為傳值調用以及傳名調用, Thunk 函數是應用於編譯器的傳名調用實現,往往是將參數放到一個臨時函數之中,再將這個臨時函數傳入函數體,這個臨時函數就叫做 Thunk 函數。 求值策略 編譯器的求值策略通常分為傳值調用以及傳名調用,在下面的例子中,將一個表達式作為參數進行傳遞,傳值調用以及傳名調用中實現的方式有所不同。 var x = 1; function s(y){ console.log(y + 1); // 3 } s(x + 1); 在上述的例子中,無論是使用傳值調用還是使用傳名調用,執行的結果都是一樣的,但是其調用過程不同: 傳值調用:首先計算 x + 1 ,然後將計算結果 2 傳遞到 s 函數,即相當於調用 s(2) 。 傳名調用:直接將 x + 1 表達式傳遞給 y ,使用時再計算 x + 1 ,即相當於計算 (x + 1) + 1 。 傳值調用與傳名調用各有利弊,傳值調用比較簡單,但是對參數求值的時候,實際上還沒用到這個參數,有可能造成沒有必要的計算。傳名調用可以解決這個問題,但是實現相對來說比較複雜。 var x = 1; function s(y){ console.log(y + 1); // 3 } s(x + 1, x + 2); 在上面這個例子中,函數 s 並沒有用到 x + 2 這個表達式求得的值,使用傳名調用的話只將表達式傳入而並未計算,只要在函數中沒有用到 x + 2 這個表達式就不會計算,使用傳值調用的話就會首先將 x + 2 的值計算然後傳入,如果沒有用到這個值,那麼就多了一次沒有必要的計算。 Thunk 函數就是作為傳名調用的實現而構建的,往往是將參數放到一個臨時函數之中,再將這個臨時函數傳入函數體,這個臨時函數就叫做 Thunk 函數。 var x = 1; function s(y){ console.log(y + 1); // 3 } s(x + 1); // 等同於 var x = 1; function s(thunk){ console.log(thunk() + 1); // 3 } var thunk = funct...

容器技術之Docker-machine

  前文我們聊了下docker容器的資源限制,回顧請參考https://www.cnblogs.com/qiuhom-1874/p/13138725.html;今天我們來聊一聊docker machine;docker machine是docker 官方提供的工具,這個工具可以在不同主機/不同系統上快速安裝、管理docker環境;docker machine 的實現原理就是通過不同的驅動來連接不同類型節點,來實現docker machine管理不同平台上的docker環境;   docker machine 安裝   1、下載二進製程序文件到本地 [root@node1 ~]# base=https://github.com/docker/machine/releases/download/v0.16.0 && > curl -L $base/docker-machine-$(uname -s)-$(uname -m) >/tmp/docker-machine && > sudo mv /tmp/docker-machine /usr/local/bin/docker-machine && > chmod +x /usr/local/bin/docker-machine % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 638 100 638 0 0 590 0 0:00:01 0:00:01 --:--:-- 590 100 26.8M 100 26.8M 0 0 11911 0 0:39:24 0:39:24 --:--:-- 16907 [root@node1 ~]# ll /usr/local/bin/docker-machine -rwxr-xr-x 1 root root 28164576 Ju...