Java 9中的进程处理
一直以來,用Java管理操作系統進程都是一項艱巨的任務。 這樣做的原因是可用的工具和API較差。 老實說,這并非沒有道理:Java并非出于此目的。 如果要管理OS進程,則可以使用所需的Shell,Perl腳本。 對于面臨更復雜任務的大型應用程序,應該使用C或C ++編寫該問題。
當您真的必須從Java管理流程時,您必須創建依賴于操作系統的代碼。 有可能,您可以查詢一些環境變量,然后可以根據操作系統實現不同的行為。 這種方法在Java 8之前都可以使用,但是它有幾個缺點。 測試成本更高,開發更復雜。 隨著Java的性質日趨廣泛和廣泛普及,對此類應用程序的需求也隨之增加。 例如,我們可以清楚地看到,2011年在StackOverflow上提出的問題https://stackoverflow.com/questions/6356340/killing-a-process-using-java有十萬多個視圖。 一些應用程序以及某些開發人員都需要針對此問題的解決方案,這實際上是解決方案,而不是解決方法。
在這種情況下,在JDK中提供API是一種解決方案。 它不會使進程處理OS獨立。 操作系統不同,進程處理是與操作系統密切相關的領域。 但是,代碼的系統相關部分移至JDK運行時,并且Java開發團隊對其進行測試,而不是對應用程序進行單獨測試。 它減輕了測試方面的負擔。 此外,由于該API已經存在,因此開發變得更加便宜,我們不需要針對BSD,OSX,Linux和Windows對其進行單獨編程,更不用說OpenVMS了。 最后,應用程序可能運行得更快。 再舉一個例子。 如果我們需要正在運行的進程的列表,那么我們必須啟動一個外部進程,該進程將進程列表轉儲到標準輸出中。 此過程的輸出必須捕獲并分析為字符串。 現在,隨著Java 9的到來,我們將有一個簡單的調用,該調用是通過調用適當的操作系統調用實現的,它不需要執行單獨的進程,也不需要解析字符串輸出來獲取Java已經不存在了。
要了解有關Java 9流程處理的所有詳細信息,您可以閱讀URL http://download.java.net/java/jdk9/docs/api/overview-summary.html上當前可用的文檔,或者您可以很快閱讀Packt的《 精通Java 9 》一書, 網址為https://www.packtpub.com/application-development/mastering-java-9 ,其中我撰寫了有關流程處理的章節。 在本文中,我將討論一些問題,為什么我們需要新的類ProcessHandle對于那些對操作系統過程以及操作系統如何工作沒有太多經驗的開發人員來說,這可能不是很明顯。
處理句柄
簡而言之, ProcessHandle的實例代表一個操作系統進程。 所有操作系統都使用PID(一個TLA縮寫“進程標識符”)標識活動進程。 這些是小(或那么小)的整數。 某些操作系統可能會使用其他名稱,例如名稱或一些神秘的字符串,但它們卻沒有使用。 沒有好處,而且碰巧所有人都使用數字來標識流程。
當我們以面向對象的方式編程時,我們會抽象問題,以便更好地解釋我們建模的問題。 但是有一條規則,就是我們不應使模型比問題本身更抽象。 這只是給應用增加了不必要的復雜性,增加了成本。 在這種情況下,使用int標識進程似乎是顯而易見的(或完全無視)。 如果操作系統不做得更抽象,那為什么要這么做呢? 僅僅因為在Java中一切都是對象? (順便說一句:不是。)
原因是PID和ProcessHandle實例之間沒有一對一的匹配。 讓我們重新閱讀本節的前兩個句子:
“…ProcessHandle代表操作系統進程。 所有操作系統都使用PID來識別活動進程……”
第二句話中只有一個單詞“活著”,相信我,這會有所作為。 盡管我們沒有直接的直接比較,但活著與死是非常不同的。 ProcessHandle實例可以保留對已從內存中擦除的進程的引用。 想象一下這樣一種情況,您查看Linux上發出“ ps –ef ”命令的進程列表,然后看到Tomcat正在吞噬CPU,并且消耗的內存越來越多,這很可能是因為所部署的應用程序存在錯誤循環。 您決定終止該進程,以便查看所顯示的pid,如果pid恰好是666 ,則發出命令“ kill -9 666 ”。 到那時,該進程已經耗盡了操作系統可能擁有的所有內存,并且由于您沒有在計算機上配置任何交換文件,因此JVM消失了,沒有任何跟蹤。 殺死進程將抱怨沒有定義的pid的進程。 也可能是操作系統已經啟動了一個完全不同的進程,而該進程恰好具有該pid。 有沒有發生過? 現在,您搖了搖頭,這是因為在您的練習中從未發生過。 默認情況下,在Linux上,他的最大pid數是32768。 實際上時間不長,但通常不會太長,以至于在發出“ ps ”和“ kill ”命令之間可以重新使用pid。 如果小型嵌入式系統將/proc/sys/kernel/pid_max設置為較小,會發生什么。 說的更小,例如適合四個位的16? 當您以交互方式發出命令時,這可能不是一個大問題,因為您在那里,并且如果系統崩潰,則可以在需要時重新啟動進程或整個系統。 如果您犯了“錯誤”,則可以采取糾正措施。 Java應用程序不是那么智能,即使在嵌入式系統中,我們也沒有機會殺死我們不想要的進程。
基于pid的流程處理
為了處理這種情況,Java具有接口ProcessHandle 。 除了pid之外,我們還有ProcessHandle 。 如果我們需要當前正在運行的進程(JVM)的ProcessHandle ,則可以調用靜態方法ProcessHandle::current (請注意,我使用了漂亮的Java 8方法句柄表示法)。 您可以在ProcessHandle實例上獲取調用getPid()的當前進程的pid,但過一會兒您將無法執行此操作。 想要進程的pid只是一個老習慣。 有手柄時就不需要它。
當您具有流程句柄時,說出processHandle,您可以獲取一個調用processHandle.children()的Stream。 這將列出直接的后代過程。 如果要“傳遞閉包”,則不僅要列出子項,還要列出子項等等,因此必須調用processHandle.descendants() 。 但是,如果您真的很貪婪,并且想在所有過程中得到幫助,該怎么辦? 然后,您應該調用靜態方法ProcessHandle::allProcesses 。
流因懶惰而聞名,僅在需要時才創建下一個元素。 在進程列表中的情況下,它會導致有趣的結果,因此在這種情況下,數據集中備份的過程流是當一個創建快照children() descendants()或allProcesses()被調用。
現在,我們可以處理流程了。 我們該怎么辦?
我們可以對其進行processHandle.destroy() ,也可以調用processHandle.destroyForcibly() 。 根據引用的堆棧溢出文章,這就是每個人都想要的。 我們還可以通過調用processHandle.isAlive()來檢查分配給該句柄的進程是否仍處于活動狀態。 您還可以訪問父進程句柄(調用processHandle.parent() 。 請注意,并非所有進程都有父進程。 當父進程終止時,它們中的一個從未擁有過,并且任何其他進程可能都是孤立的。 因此,此方法的返回值是Optional 。 Java 9在Optional類中具有不錯的新功能,但這是另外一回事了,這里我們重點介紹流程。
如果該進程仍然存在,但是我們要等待該進程終止,則可以采用一種現代的異步方式來完成它。 我們可以從調用processHandle.onExit()的過程句柄中獲取CompletableFuture ,該過程將在過程終止時完成。 Java 9在CompletableFuture類中也具有新功能,但這是另外CompletableFuture了,這里我們將重點放在流程上。 我會重演嗎?
ProcessHandle接口內部有一個稱為Info的接口。 我們可以從流程句柄中調用processHandle.info()獲得信息的實例。 通過此實例,我們可以訪問參數(作為可選字符串數組),訪問命令行(作為可選字符串),訪問命令(作為字符串)以及用戶也屬于可選字符串。 我們還可以以可選的Instant和Duration形式獲取有關啟動進程的信息以及有關CPU總使用量的信息。 這些新類是在Java 8中引入的,而Java 9具有新功能……好吧,它開始變得很無聊。
摘要
所有這些功能我們能做什么? 在書中,我提到我創建了一個簡單的過程控制應用程序。 我不得不在2006年左右用perl創建類似的產品。 它按照配置文件中的描述啟動進程,如果其中任何一個失敗,它將重新啟動。 但這只是一個例子。 在其他情況下,可以方便地進行處理。 您要填寫表格并將其轉換為PDF。 為此,您可以使用命令行參數啟動一些文字處理程序。 任務正在排隊,并且一個接一個地啟動,以保持合理的性能,您最多可以在n個進程中轉換可配置的n個文檔。 如果某個過程花費的時間太長,您將其殺死,則將有關該消息的信息發送給啟動請求的人員到您的轉換服務器,并安排其在夜間或更不繁忙的時段運行。
我們可以使用Java開發此類程序,而無需使用外部shell,python或perl腳本,這只會使項目更簡單,更便宜。
翻譯自: https://www.javacodegeeks.com/2017/07/process-handling-java-9.html
總結
以上是生活随笔為你收集整理的Java 9中的进程处理的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: web.xml.jsf_使用JSF 2.
- 下一篇: 苏州高新区备案制教师待遇(苏州高新区备案