本篇內(nèi)容主要講解“Java中怎么鎖文件”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學(xué)習(xí)“Java中怎么鎖文件”吧!
為企業(yè)提供成都網(wǎng)站建設(shè)、網(wǎng)站建設(shè)、網(wǎng)站優(yōu)化、網(wǎng)絡(luò)營銷推廣、競價托管、品牌運營等營銷獲客服務(wù)。創(chuàng)新互聯(lián)建站擁有網(wǎng)絡(luò)營銷運營團隊,以豐富的互聯(lián)網(wǎng)營銷經(jīng)驗助力企業(yè)精準(zhǔn)獲客,真正落地解決中小企業(yè)營銷獲客難題,做到“讓獲客更簡單”。自創(chuàng)立至今,成功用技術(shù)實力解決了企業(yè)“網(wǎng)站建設(shè)、網(wǎng)絡(luò)品牌塑造、網(wǎng)絡(luò)營銷”三大難題,同時降低了營銷成本,提高了有效客戶轉(zhuǎn)化率,獲得了眾多企業(yè)客戶的高度認(rèn)可!當(dāng)讀寫文件時,需要確保有適當(dāng)?shù)奈募i定機制,來保證基于并發(fā)I/O應(yīng)用程序的數(shù)據(jù)完整性。
「本教程中, 我們將介紹使用 Java NIO 庫實現(xiàn)這一點的各種方法?!?/strong>
「一般來說,有兩種鎖」:
簡單地說,在寫操作完成時,獨占鎖防止所有其他操作(包括讀操作)。
相反,共享鎖允許多個進程同時讀取。讀鎖的目的是防止另一個進程獲取寫鎖。通常,處于一致狀態(tài)的文件確實應(yīng)該被任何進程讀取。
在下一節(jié)中,我們將看到Java如何處理這些類型的鎖。
Java NIO庫支持在操作系統(tǒng)級別鎖定文件。FileChannel 中的lock() 和*tryLock()*方法就是為了這個而存在。
我們可以通過 FileInputStream, FileOutputStream,RandomAccessFile 來獲取FileChannel,三者均可通過 getChannel() 方法返回 FileChannel對象.
或者, 我們可以直接通過靜態(tài)方法 open 來創(chuàng)建 FileChannel :
try (FileChannel channel = FileChannel.open(path, openOptions)) { // write to the channel }
接下來,我們將回顧在Java中獲取獨占鎖和共享鎖的不同方式。要了解有關(guān)文件通道的更多信息,請查看[Guide to Java FileChanne 教程。
正如我們已經(jīng)了解到的,在寫入文件時,「我們可以使用獨占鎖」防止其他進程讀取或?qū)懭胛募?/p>
我們通過調(diào)用 FileChannel 類上的 lock() 或 tryLock()) 來獲得獨占鎖。我們還可以使用它們的重載方法:
在這些情況下,shared參數(shù)必須設(shè)置為false。
要獲得獨占鎖,必須使用可寫的文件通道。我們可以通過 FileOutputStream 或 RandomAccessFile 的 getChannel() 方法創(chuàng)建它?;蛘撸缜八?,我們可以使用 FileChannel 類的靜態(tài)方法:open。我們只需要將第二個參數(shù)設(shè)置為StandardOpenOption.APPEND :
try (FileChannel channel = FileChannel.open(path, StandardOpenOption.APPEND)) { // write to channel }
從 FileOutputStream 創(chuàng)建的 FileChannel 是可寫的。因此,我們可以獲得一個獨占鎖:
try (FileOutputStream fileOutputStream = new FileOutputStream("/tmp/testfile.txt"); FileChannel channel = fileOutputStream.getChannel(); FileLock lock = channel.lock()) { // write to the channel }
在這里,channel.lock() 要么阻塞直到獲得一個鎖,要么拋出一個異常。例如,如
果指定的區(qū)域已鎖定,則會引發(fā)OverlappingFileLockException。有關(guān)可能的異常的完整列表,請參見Javadoc。我們還可以使用 channel.tryLock() 執(zhí)行非阻塞鎖。如果由于另一個程序持有一個重疊的鎖而無法獲取鎖,則返回null。如果由于任何其他原因未能執(zhí)行此操作,則會引發(fā)相應(yīng)的異常。
使用 RandomAccessFile,我們需要設(shè)置 [constructor](/tupian/20230522/RandomAccessFile.html java.lang.String)) 方法的第二個參數(shù)。
在這里,我們將使用讀寫權(quán)限打開文件:
try (RandomAccessFile file = new RandomAccessFile("/tmp/testfile.txt", "rw"); FileChannel channel = file.getChannel(); FileLock lock = channel.lock()) { // write to the channel }
如果我們以只讀模式打開文件,并嘗試向其通道進行寫入操作,將會拋出 NonWritableChannelException 異常。
如前所述,獨占鎖需要一個可寫通道。因此,我們無法通過從 FileInputStream 創(chuàng)建的 FileChannel 獲得獨占鎖:
try (RandomAccessFile file = new RandomAccessFile("/tmp/testfile.txt", "rw"); FileChannel channel = file.getChannel(); FileLock lock = channel.lock()) { // write to the channel }
在上面的例子中,lock() 方法將拋出一個 nonwriteablechannelexception 。實際上,這是因為我們正在對一個創(chuàng)建只讀通道的 FileInputStream 調(diào)用 getChannel。這個例子只是為了證明我們不能寫到一個不可寫的通道。事實上,我們不會捕捉并重新拋出異常。
記住,共享鎖也稱為讀 鎖。因此,要獲得讀鎖,我們必須使用可讀的文件通道。
這樣的 FileChannel 可以通過調(diào)用 FileInputStream 或 RandomAccessFile 上的 getChannel() 方法獲得。同樣,另一個選項是使用 FileChannel 類的靜態(tài) open 方法。在這種情況下,我們將第二個參數(shù)設(shè)置為 StandardOpenOption.READ 。
try (RandomAccessFile file = new RandomAccessFile("/tmp/testfile.txt", "rw"); FileChannel channel = file.getChannel(); FileLock lock = channel.lock()) { // write to the channel }
這里要注意的一點是,我們選擇通過調(diào)用 lock(0, Long.MAX_VALUE, true) 來鎖定整個文件。通過將前兩個參數(shù)更改為不同的值,我們還可以只鎖定文件的特定區(qū)域。對于共享鎖,第三個參數(shù)必須設(shè)置為true。
為了簡單起見,我們將在下面的所有示例中鎖定整個文件,但請記住,我們始終可以鎖定文件的特定區(qū)域。
從 FileInputStream 獲得的 FileChannel 是可讀的。因此,我們可以獲得一個共享鎖:
try (FileInputStream fileInputStream = new FileInputStream("/tmp/testfile.txt"); FileChannel channel = fileInputStream.getChannel(); FileLock lock = channel.lock(0, Long.MAX_VALUE, true)) { // read from the channel }
在上面的代碼片段中,將成功調(diào)用通道上的 lock() 。這是因為共享鎖只要求通道是可讀的就行。
這次,我們只需要使用 ''讀" 權(quán)限打開文件即可:
try (RandomAccessFile file = new RandomAccessFile("/tmp/testfile.txt", "r"); FileChannel channel = file.getChannel(); FileLock lock = channel.lock(0, Long.MAX_VALUE, true)) { // read from the channel }
在本例中,我們創(chuàng)建了一個具有讀取權(quán)限的RandomAccessFile對象,然后從中創(chuàng)建一個可讀通道,從而創(chuàng)建一個共享鎖。
因此,我們無法通過從 FileOutputStream 創(chuàng)建的 FileChannel 獲取共享鎖:
Path path = Files.createTempFile("foo","txt"); try (FileOutputStream fis = new FileOutputStream(path.toFile()); FileLock lock = fis.getChannel().lock(0, Long.MAX_VALUE, true)) { // unreachable code } catch (NonWritableChannelException e) { // handle exception }
在本例中,調(diào)用 lock() 嘗試獲取從 FileOutputStream 創(chuàng)建的通道上的共享鎖。這樣的通道是只寫的。它不能滿足通道必須可讀的需要。這將觸發(fā)一個NonWritableChannelException。
同樣,這段代碼只是為了證明我們不能從一個不可讀的通道中讀取。
實際上,使用文件鎖是困難的;鎖定機制是不可移植的。我們需要考慮到這一點來設(shè)計鎖定邏輯。
在POSIX系統(tǒng)中,鎖是建議性的。讀取或?qū)懭虢o定文件的不同進程必須就鎖定協(xié)議達成一致。這將確保文件的完整性。操作系統(tǒng)本身不會強制任何鎖定。
在Windows上,除非允許共享,否則鎖將是獨占的。討論操作系統(tǒng)特定機制的優(yōu)點或缺點超出了本文的討論范圍。然而,在實現(xiàn)鎖定機制時,了解這些細(xì)微差別很重要。
在本教程中,我們回顧了在Java中獲取文件鎖的幾種不同選項。
首先,我們首先了解兩種主要的鎖定機制,以及Java NIO庫如何促進鎖定文件。然后,我們?yōu)g覽了一系列簡單的示例,這些示例顯示我們可以在應(yīng)用程序中獲得獨占和共享鎖。我們還研究了使用文件鎖時可能遇到的典型異常類型。
到此,相信大家對“Java中怎么鎖文件”有了更深的了解,不妨來實際操作一番吧!這里是創(chuàng)新互聯(lián)網(wǎng)站,更多相關(guān)內(nèi)容可以進入相關(guān)頻道進行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!