JavaRush /Java Blog /Random EN /Coffee break #171. How to use the synchronized keyword. F...

Coffee break #171. How to use the synchronized keyword. File Handling in Java

Published in the Random EN group

How to use the synchronized keyword

Source: Medium Today you will learn in what cases and how to correctly use the synchronized keyword in the Java programming language. Coffee break #171.  How to use the synchronized keyword.  File Processing in Java - 1Modifiers are certain keywords present in Java with the help of which we can make changes to the characteristics of a variable, method or class and limit its scope. The Java language has a fairly large set of modifiers. Modifiers in Java are divided into two types - Access Modifiers and Non -Access modifiers.

Modifiers without access

Non-accessible modifiers provide the JVM with information about the characteristics of a class, method, or variable. There are seven types of non-access modifiers in Java:
  • final
  • static
  • abstract
  • synchronized
  • volatile
  • transient
  • native
In this article, we will take a closer look at the synchronized keyword . First, let's define where and when to use it.

In what cases is synchronized used?

In Java, the synchronized keyword is used to provide access control to a method or block of code. When a thread attempts to execute a synchronized method or block of code, it must first acquire a lock. Once you have received the lock, you can begin execution. However, any other thread attempting to execute the same synchronized method or block of code will be blocked until the first thread releases the lock. This ensures that only one thread can execute code at a time, which is important for maintaining data integrity. The synchronized keyword can be used with both static and non-static methods, as well as blocks of code.
  • When used with static methods, all threads compete for the same lock. This can impact performance, so it's best to avoid synchronizing static methods unless absolutely necessary.

  • When used with non-static methods, each instance of the class will have its own lock, so multiple threads can simultaneously execute synchronized code from different instances. This is usually the preferred approach.

  • When used with code blocks, a lock is acquired on an object that is passed to the synchronized statement . This allows multiple threads to simultaneously execute synchronized blocks of code from different objects.

Thus, the synchronized keyword is a powerful tool for controlling concurrent data access in Java applications. When used correctly, it can help ensure data integrity and improve performance.

Examples of using

1. Synchronized block

public class Counter {
  private int count = 0;

  public int getCount() {
    synchronized (this) {
      return count;
    }
  }

  public void increment() {
    synchronized (this) {
      count++;
    }
  }
}
There are two blocks of code here that access the counter. The simplest of these is the get method , which simply reads the value. At first glance, the increment method appears to contain one line of code. But remember that the increment operation must read the current value, add one to it, and write the new value back to memory. In other words, there are three sub-operations that we want to perform without interruption from other threads. For example, placing it on the other side or making the increment operation atomic . When we prefix two blocks of code with the synchronized keyword , it's important to note that we're also marking them as synchronized for a specific object , as shown in our example. This means that if we have multiple Counter objects , then different threads can update those different counters at the same time. But two threads cannot simultaneously run synchronized blocks on the same Counter instance .

2. Synchronized method

public class SynchronizedCounter {
    private int c = 0;

    public synchronized void increment() {
        c++;
    }

    public synchronized void decrement() {
        c--;
    }

    public synchronized int value() {
        return c;
    }
}
If count is an instance of SynchronizedCounter , then synchronizing these methods has two effects:
  • First, two calls to synchronized methods on the same object cannot interleave. When one thread executes a synchronized method on an object, all other threads that call synchronized methods on the same block of the object pause until the first thread finishes working on the object.

  • Second, when the synchronized method exits, it automatically sets the value to “happens-before” on any subsequent calls to the synchronized method on the same object. This ensures that changes to the object's state are visible to all threads.

Remember that knowing why, how and when to use synchronized as well as other modifiers comes with experience, and experience comes with time.

File Handling in Java

Source: Usemynotes The content of this post is about file processing in Java. You will become familiar with file processing operations, the methods of the File class, and the types of streams. Coffee break #171.  How to use the synchronized keyword.  File Processing in Java - 2Working with files is an integral part of any programming language. Using files, a program can store data on a storage device. Performing various actions on a file, such as reading or writing, requires processing the file. File processing is defined as reading from a file and writing to a file. To create a file object and handle different file formats, we can use the File class from the java.io package . If we want to use the File class, we need to create an object of the File class and specify the file name or path. Using this class, we can access file metadata such as file name, file size, permissions, file type and so on.
// 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");
}
}
To import the File class, you can also use import java.io.File instead of import java.io.* . Now let's learn about threads as Java uses threads to perform input/output (I/O) operations on a file.

What is a thread in Java?

Stream is a sequence of data. It can also be defined as a sequence of bytes. A stream can be used to represent either an input source or a destination. The source and destination can be files on disk, arrays, text files, and so on. The input stream reads or retrieves data from the source, and the output stream writes data to the destination. There are two types of streams:

Byte stream

A Byte Stream is used to perform read and write operations on byte data. The process of processing a byte stream file is defined as performing input using byte data. There are many classes related to byte streams, but the most commonly used classes are FileInputStream and 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();
 }
}
In the above example, we are reading data from the source file and writing the data to the destination. -1 indicates the end of the file. So reading from the source file will stop when -1 appears.

Character stream

Character Stream is used to perform read and write operations on character data. The process of processing a file with a character stream is the process of executing input data with characters. There are many character stream classes available, but the most commonly used classes include FileWriter and FileReader . Now let's discuss some methods of the File class .

Methods of the File class in Java

canRead()

This file class method checks whether the file is readable and returns a Boolean value, that is, true or false .

canWrite()

This is a file class method that checks whether a file is writable and returns a boolean value, i.e. true or false.

exists()

This is a file class method used to check for the existence of a given file and returns a boolean value.

createNewFile()

When we want to create a new empty file, use this file class method. It returns a boolean value.

delete()

This is a file class method used to delete a file and return a boolean value.

getAbsolutePath()

This method is used to return the absolute path of a file. getName() This is a method used to return a string value which is the name of the file.

list()

It returns an array of strings representing all the files in the directory.

length()

This file class method returns the file size in bytes.

mkdir()

This is a file class method that is used to create a new directory. Let's take a look at the various file operations available in Java and how to use them.

What are file operations in Java?

When processing Java files, we can perform the following operations on a file:
  • Creating a file
  • Writing data to a file
  • Reading data from a file
  • Deleting a file
  • Getting information about a file
  • Creating a file
In Java, we can create a file using the createNewFile() method of the File class . This method returns true if the file is created, otherwise returns false if the file already exists.
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.");
 }
}

Writing data to a file

A write operation to a file means storing data in a file. To perform write operations on a file, we use the write() method along with the FileWriter class . To close a stream and get allocated resources, we must use the close() method .
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();
   }
}

Reading from a file

A read operation means accessing or retrieving data stored in a file. To perform a write operation on a file, we will use the Scanner class along with the hasNextLine() and nextLine() methods to retrieve data from the file. To close a stream, we must use the close() method .
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();
   }
}

Deleting a file

When processing Java files, we can delete a file using the delete() method of the File class . There is no need to close the file using the close() function since the FileWriter and Scanner classes are not used to delete the file .
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.");
   }
}

Getting information about a file

There are several methods in Java to get information about a file. They have already been mentioned earlier in the methods of the file class.
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());
  }
}
Let's look at how one Java program works to determine whether a number is even or odd using a byte array stream while processing Java files. To write this program, we will use the ByteArrayInputStream class from the java.io package . This class contains a buffer that is used to read a byte array as an input stream. Below is the code to check if numbers are even or odd.
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.");
     }
   }
}
I hope the information presented here was useful to you. To better understand working with files in Java, you should try to implement all the file and operation methods yourself.
Comments
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION