如何使用synchronized关键字
来源:Medium 今天您将了解在什么情况下以及如何正确使用Java 编程语言中的synchronized 关键字。 修饰符是 Java 中存在的某些关键字,借助它们我们可以更改变量、方法或类的特征并限制其范围。Java 语言有相当多的修饰符集。Java 中的修饰符分为两种类型 -访问修饰符和非访问修饰符。无访问权限的修改器
不可访问修饰符为 JVM 提供有关类、方法或变量的特征的信息。Java中有七种类型的非访问修饰符:- 最终的
- 静止的
- 抽象的
- 同步的
- 易挥发的
- 短暂的
- 本国的
什么情况下使用synchronized?
在 Java 中,synchronized 关键字用于提供对方法或代码块的访问控制。当线程尝试执行同步方法或代码块时,它必须首先获取锁。一旦收到锁,就可以开始执行。但是,任何其他尝试执行相同同步方法或代码块的线程都将被阻塞,直到第一个线程释放锁。这可确保一次只有一个线程可以执行代码,这对于维护数据完整性非常重要。Synchronized 关键字可以与静态和非静态方法以及代码块一起使用。-
与静态方法一起使用时,所有线程都会竞争同一锁。这可能会影响性能,因此除非绝对必要,否则最好避免同步静态方法。
-
当与非静态方法一起使用时,类的每个实例都将拥有自己的锁,因此多个线程可以同时执行来自不同实例的同步代码。这通常是首选方法。
-
当与代码块一起使用时,会在传递给同步语句的对象上获取锁。这允许多个线程同时执行来自不同对象的同步代码块。
使用示例
1. 同步块
public class Counter {
private int count = 0;
public int getCount() {
synchronized (this) {
return count;
}
}
public void increment() {
synchronized (this) {
count++;
}
}
}
这里有两个访问计数器的代码块。其中最简单的是get方法,它只是读取值。乍一看,increment 方法似乎包含一行代码。但请记住,增量操作必须读取当前值,加一,然后将新值写回内存。换句话说,我们希望在不被其他线程中断的情况下执行三个子操作。例如,将其放在另一侧或使增量操作原子化。当我们在两个代码块前面加上synchronized关键字时,需要注意的是,我们还将它们标记为特定对象的同步 ,如我们的示例所示。这意味着如果我们有多个Counter对象,那么不同的线程可以同时更新这些不同的计数器。但是两个线程不能同时在同一个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的实例,那么同步这些方法有两个效果:
-
首先,对同一对象上的同步方法的两次调用不能交错。当一个线程在对象上执行同步方法时,在该对象的同一块上调用同步方法的所有其他线程都会暂停,直到第一个线程完成对该对象的处理。
-
其次,当同步方法退出时,它会在同一对象上对同步方法的任何后续调用中自动将值设置为“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.File而不是import java.io.*。现在让我们了解线程,因为 Java 使用线程对文件执行输入/输出 (I/O) 操作。
Java中什么是线程?
流是数据序列。它也可以定义为字节序列。流可用于表示输入源或目的地。源和目标可以是磁盘、阵列、文本文件等上的文件。输入流从源读取或检索数据,输出流将数据写入目标。有两种类型的流:字节流
字节流用于对字节数据执行读写操作。处理字节流文件的过程被定义为使用字节数据执行输入。与字节流相关的类有很多,但最常用的类是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。存在()
这是一个文件类方法,用于检查给定文件是否存在并返回一个布尔值。创建新文件()
当我们想要创建一个新的空文件时,使用这个文件类方法。它返回一个布尔值。删除()
这是一个文件类方法,用于删除文件并返回一个布尔值。获取绝对路径()
该方法用于返回文件的绝对路径。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()方法来删除文件。无需使用close()函数关闭文件,因为FileWriter和Scanner类不用于删除文件。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