同期キーワードの使い方
出典: Medium 今日は、Java プログラミング言語で synchronized キーワードをどのような場合に、どのように正しく使用するかを学びます。 修飾子はJava に存在する特定のキーワードであり、これを使用すると、変数、メソッド、またはクラスの特性に変更を加え、その範囲を制限できます。Java 言語には、かなり大規模な修飾子のセットがあります。Java の修飾子は、アクセス修飾子と非アクセス修飾子の 2 つのタイプに分類されます。アクセス権のない修飾子
アクセスできない修飾子は、クラス、メソッド、または変数の特性に関する情報を JVM に提供します。Java には 7 種類の非アクセス修飾子があります。- 最後の
- 静的
- 抽象的な
- 同期した
- 揮発性の
- 一時的な
- ネイティブ
同期はどのような場合に使用されますか?
Java では、メソッドまたはコード ブロックへのアクセス制御を提供するために synchronized キーワードが使用されます。スレッドが同期されたメソッドまたはコードのブロックを実行しようとすると、まずロックを取得する必要があります。ロックを受け取ったら、実行を開始できます。ただし、同じ同期メソッドまたはコードのブロックを実行しようとする他のスレッドは、最初のスレッドがロックを解放するまでブロックされます。これにより、一度に 1 つのスレッドだけがコードを実行できるようになります。これは、データの整合性を維持するために重要です。synchronized キーワードは、コードのブロックだけでなく、静的メソッドと非静的メソッドの両方で使用できます。-
静的メソッドで使用すると、すべてのスレッドが同じロックをめぐって競合します。これはパフォーマンスに影響を与える可能性があるため、絶対に必要な場合を除き、静的メソッドの同期は避けることをお勧めします。
-
非静的メソッドで使用すると、クラスの各インスタンスに独自のロックが設定されるため、複数のスレッドが異なるインスタンスから同期されたコードを同時に実行できます。通常、これが推奨されるアプローチです。
-
コード ブロックとともに使用すると、 synchronizedステートメントに渡されるオブジェクトに対してロックが取得されます。これにより、複数のスレッドが異なるオブジェクトから同期されたコード ブロックを同時に実行できるようになります。
使用例
1. 同期ブロック
public class Counter {
private int count = 0;
public int getCount() {
synchronized (this) {
return count;
}
}
public void increment() {
synchronized (this) {
count++;
}
}
}
ここには、カウンターにアクセスする 2 つのコード ブロックがあります。これらの中で最も単純なものは、値を読み取るだけのgetメソッドです。一見すると、increment メソッドには 1 行のコードが含まれているように見えます。ただし、インクリメント操作では、現在の値を読み取り、それに 1 を加算し、新しい値をメモリに書き戻す必要があることに注意してください。言い換えれば、他のスレッドからの中断なしに実行したいサブ操作が 3 つあります。たとえば、反対側に配置したり、インクリメント操作をアトミックにしたりします。2 つのコード ブロックの先頭にsynchronizedキーワードを付ける場合、例に示すように、それらのブロックが特定のオブジェクトに対して同期済み としてマークされることに注意することが重要です。これは、複数のCounterオブジェクトがある場合、異なるスレッドがそれらの異なるカウンターを同時に更新できることを意味します。ただし、2 つのスレッドが同じCounterインスタンス上で同期されたブロックを同時に実行することはできません。
2. 同期方式
public class SynchronizedCounter {
private int c = 0;
public synchronized void increment() {
c++;
}
public synchronized void decrement() {
c--;
}
public synchronized int value() {
return c;
}
}
count がSynchronizedCounterのインスタンスである 場合、これらのメソッドを同期すると、次の 2 つの効果があります。
-
まず、同じオブジェクト上の同期メソッドへの 2 つの呼び出しをインターリーブすることはできません。1 つのスレッドがオブジェクトに対して同期メソッドを実行すると、オブジェクトの同じブロックに対して同期メソッドを呼び出す他のすべてのスレッドは、最初のスレッドがオブジェクトでの作業を終了するまで一時停止します。
-
次に、同期メソッドが終了すると、同じオブジェクト上の同期メソッドに対する後続の呼び出しで、値が自動的に「happens-before」に設定されます。これにより、オブジェクトの状態への変更がすべてのスレッドに表示されるようになります。
Java でのファイル処理
出典: Usemynotes この投稿の内容は Java でのファイル処理に関するものです。ファイル処理操作、File クラスのメソッド、およびストリームの種類について理解できるようになります。 ファイルの操作は、どのプログラミング言語にとっても不可欠な部分です。プログラムはファイルを使用して、ストレージ デバイスにデータを保存できます。ファイルに対して読み取りや書き込みなどのさまざまなアクションを実行するには、ファイルを処理する必要があります。ファイル処理は、ファイルからの読み取りとファイルへの書き込みとして定義されます。ファイル オブジェクトを作成し、さまざまなファイル形式を処理するには、java.ioパッケージのFileクラスを使用できます。File クラスを使用する場合は、 Fileクラスのオブジェクトを作成し、ファイル名またはパスを指定する必要があります。このクラスを使用すると、ファイル名、ファイル サイズ、アクセス許可、ファイル タイプなどのファイル メタデータにアクセスできます。// importing all the classes of java.io
import java.io.*;
class FileHandle {
public static void main(String[] arr) {
// an object of File class is created.
File f=new File("demo.txt");
}
}
Fileクラス をインポートするには、 import java.io.*の代わりにimport java.io.Fileを使用することもできます。ここで、Java がスレッドを使用してファイルの入出力 (I/O) 操作を実行するためのスレッドについて学習しましょう。
Java のスレッドとは何ですか?
ストリームは一連のデータです。バイトのシーケンスとして定義することもできます。ストリームは、入力ソースまたは宛先のいずれかを表すために使用できます。ソースと宛先は、ディスク上のファイル、アレイ、テキスト ファイルなどにすることができます。入力ストリームはソースからデータを読み取るか取得し、出力ストリームは宛先にデータを書き込みます。ストリームには次の 2 種類があります。バイトストリーム
バイト ストリームは、バイト データの読み取りおよび書き込み操作を実行するために使用されます。バイトストリームファイルを処理するプロセスは、バイトデータを使用して入力を実行することとして定義されます。バイト ストリームに関連するクラスは多数ありますが、最も一般的に使用されるクラスはFileInputStreamとFileOutputStreamです。import java.io.*;
public class FileHandle{
public static void main(String []arr) throws IOException{
FileInputStream fin=new FileInputStream("source_file.txt");
FileOutputStream fout=new FileOutputStream("destination_file.txt");
int character;
while((character=fin.read())!=-1)
{
System.out.print((char)character);
// writing to destination file
fout.write((char)character);
}
// closing source_file.txt
fin.close();
// closing destination_file.txt
fout.close();
}
}
上の例では、ソース ファイルからデータを読み取り、そのデータを宛先に書き込みます。-1 はファイルの終わりを示します。したがって、-1 が表示されるとソース ファイルからの読み取りが停止します。
文字ストリーム
文字ストリームは、文字データの読み取りおよび書き込み操作を実行するために使用されます。文字ストリームによるファイルの処理は、入力データを文字で実行する処理です。利用可能な文字ストリーム クラスは多数ありますが、最も一般的に使用されるクラスにはFileWriterとFileReaderがあります。次に、 Fileクラスのいくつかのメソッドについて説明します。JavaのFileクラスのメソッド
読める()
このファイル クラス メソッドは、ファイルが読み取り可能かどうかを確認し、ブール値、つまりtrueまたはfalseを返します。書ける()
これは、ファイルが書き込み可能かどうかをチェックし、ブール値、つまり true または false を返すファイル クラス メソッドです。存在します()
これは、指定されたファイルの存在を確認するために使用されるファイル クラス メソッドであり、ブール値を返します。createNewFile()
新しい空のファイルを作成したい場合は、このファイルクラスメソッドを使用します。ブール値を返します。消去()
これは、ファイルを削除し、ブール値を返すために使用されるファイル クラス メソッドです。get絶対パス()
このメソッドは、ファイルの絶対パスを返すために使用されます。getName() これは、ファイルの名前である文字列値を返すために使用されるメソッドです。リスト()
ディレクトリ内のすべてのファイルを表す文字列の配列を返します。長さ()
このファイル クラス メソッドは、ファイル サイズをバイト単位で返します。mkdir()
これは、新しいディレクトリを作成するために使用されるファイル クラスのメソッドです。Java で利用できるさまざまなファイル操作とその使用方法を見てみましょう。Java におけるファイル操作とは何ですか?
Java ファイルを処理する場合、ファイルに対して次の操作を実行できます。- ファイルの作成
- ファイルへのデータの書き込み
- ファイルからのデータの読み取り
- ファイルの削除
- ファイルに関する情報の取得
- ファイルの作成
import java.io.*;
public class FileHandle{
public static void main(String []arr) throws IOException{
// an object of file class
File f=new File("demo.txt");
// creating a new file
Boolean result=f.createNewFile();
if(result)
System.out.print(f+" created successfully.");
else
System.out.format("%s","File cannot be created due to some error.");
}
}
ファイルへのデータの書き込み
ファイルへの書き込み操作とは、データをファイルに保存することを意味します。ファイルに対して書き込み操作を実行するには、write()メソッドとFileWriterクラスを使用します。ストリームを閉じてリソースの割り当てを取得するには、close()メソッドを使用する必要があります。import java.io.*;
public class FileHandle{
public static void main(String []arr) throws IOException{
// creating a new file and writing data to a file
FileWriter fw=new FileWriter("demo.txt");
String s="Welcome, this is tutorial of Java File Handling.";
fw.write(s);
// closing a file
fw.close();
}
}
ファイルからの読み取り
読み取り操作とは、ファイルに保存されているデータにアクセスまたは取得することを意味します。ファイルに対して書き込み操作を実行するには、Scanner クラスをhasNextLine()およびnextLine()メソッドとともに使用して、ファイルからデータを取得します。ストリームを閉じるには、close()メソッドを使用する必要があります。import java.io.*;
import java.util.Scanner;
public class FileHandle{
public static void main(String []arr) throws IOException{
File f=new File("demo.txt");
Scanner sc=new Scanner(f);
while(sc.hasNextLine())
{
String str=sc.nextLine();
System.out.println(str);
}
// closing a file
sc.close();
}
}
ファイルの削除
Java ファイルを処理する場合、 Fileクラスのdelete()メソッドを使用してファイルを削除できます。FileWriter クラスとScannerクラスはファイルの削除に使用されないため、close()関数を使用してファイルを閉じる必要はありません。import java.io.*;
public class FileHandle{
public static void main(String []arr) throws IOException{
File f=new File("demo.txt");
Boolean result=f.delete();
if(result)
System.out.print(f+" deleted successfully.");
else
System.out.format("%s","File cannot be deleted due to some error.");
}
}
ファイルに関する情報の取得
Java には、ファイルに関する情報を取得するメソッドがいくつかあります。これらについては、ファイル クラスのメソッドですでに説明しました。import java.io.*;
public class FileHandle{
public static void main(String []arr) throws IOException{
File file=new File("demo.txt");
file.createNewFile();
String filename=file.getName();
System.out.println("File Name is "+filename);
System.out.println("Absolute path of "+filename+" : "+file.getAbsolutePath());
System.out.print("length of "+filename+" : "+file.length());
System.out.println("Is "+filename+" readable? "+file.canRead());
System.out.println("Is "+filename+" writable? "+file.canWrite());
System.out.println("Is "+filename+" exists? "+file.exists());
}
}
ある Java プログラムが Java ファイルの処理中にバイト配列ストリームを使用して数値が偶数か奇数かを判断する方法を見てみましょう。このプログラムを作成するには、 java.ioパッケージのByteArrayInputStreamクラスを使用します。このクラスには、バイト配列を入力ストリームとして読み取るために使用されるバッファーが含まれています。以下は、数値が偶数か奇数かをチェックするコードです。
import java.io.*;
public class FileHandle{
public static void main(String []arr) throws IOException{
byte []buffer={10,40,81,23,32,100,57};
ByteArrayInputStream by=new ByteArrayInputStream(buffer);
int character=0;
while((character=by.read())!=-1)
{
int number=character;
if(number%2==0)
System.out.println(number+" is an even number.");
else
System.out.println(number+" is an odd number.");
}
}
}
ここで紹介した情報がお役に立てば幸いです。Java でのファイルの操作をより深く理解するには、すべてのファイルと操作メソッドを自分で実装してみる必要があります。
GO TO FULL VERSION