JavaRush /Blog Java /Random-VI /Nghỉ giải lao #171. Cách sử dụng từ khóa được đồng bộ hóa...

Nghỉ giải lao #171. Cách sử dụng từ khóa được đồng bộ hóa. Xử lý tệp trong Java

Xuất bản trong nhóm

Cách sử dụng từ khóa được đồng bộ hóa

Nguồn: Medium Hôm nay bạn sẽ tìm hiểu những trường hợp nào và cách sử dụng chính xác từ khóa được đồng bộ hóa trong ngôn ngữ lập trình Java. Nghỉ giải lao #171.  Cách sử dụng từ khóa được đồng bộ hóa.  Xử lý tệp trong Java - 1Công cụ sửa đổi là một số từ khóa nhất định có trong Java với sự trợ giúp của chúng, chúng ta có thể thay đổi các đặc điểm của một biến, phương thức hoặc lớp và giới hạn phạm vi của nó. Ngôn ngữ Java có một bộ sửa đổi khá lớn. Công cụ sửa đổi trong Java được chia thành hai loại - Công cụ sửa đổi truy cập và Công cụ sửa đổi không truy cập.

Công cụ sửa đổi không có quyền truy cập

Các công cụ sửa đổi không thể truy cập cung cấp cho JVM thông tin về các đặc điểm của một lớp, phương thức hoặc biến. Có bảy loại công cụ sửa đổi không truy cập trong Java:
  • cuối cùng
  • tĩnh
  • trừu tượng
  • đồng bộ
  • bay hơi
  • tạm thời
  • tự nhiên
Trong bài viết này, chúng ta sẽ xem xét kỹ hơn về từ khóa được đồng bộ hóa . Đầu tiên, hãy xác định vị trí và thời điểm sử dụng nó.

Đồng bộ hóa được sử dụng trong trường hợp nào?

Trong Java, từ khóa được đồng bộ hóa được sử dụng để cung cấp khả năng kiểm soát truy cập vào một phương thức hoặc khối mã. Khi một luồng cố gắng thực thi một phương thức hoặc khối mã được đồng bộ hóa, trước tiên nó phải có được một khóa. Khi bạn đã nhận được khóa, bạn có thể bắt đầu thực hiện. Tuy nhiên, bất kỳ luồng nào khác cố gắng thực thi cùng một phương thức hoặc khối mã được đồng bộ hóa sẽ bị chặn cho đến khi luồng đầu tiên giải phóng khóa. Điều này đảm bảo rằng mỗi lần chỉ có một luồng có thể thực thi mã, điều này rất quan trọng để duy trì tính toàn vẹn của dữ liệu. Từ khóa được đồng bộ hóa có thể được sử dụng với cả phương thức tĩnh và không tĩnh, cũng như các khối mã.
  • Khi được sử dụng với các phương thức tĩnh, tất cả các luồng sẽ cạnh tranh để có cùng một khóa. Điều này có thể ảnh hưởng đến hiệu suất, vì vậy tốt nhất nên tránh đồng bộ hóa các phương thức tĩnh trừ khi thực sự cần thiết.

  • Khi được sử dụng với các phương thức không tĩnh, mỗi phiên bản của lớp sẽ có khóa riêng, do đó nhiều luồng có thể thực thi đồng thời mã được đồng bộ hóa từ các phiên bản khác nhau. Đây thường là cách tiếp cận ưa thích.

  • Khi được sử dụng với các khối mã, một khóa sẽ được lấy trên một đối tượng được chuyển đến câu lệnh được đồng bộ hóa . Điều này cho phép nhiều luồng thực thi đồng thời các khối mã được đồng bộ hóa từ các đối tượng khác nhau.

Do đó, từ khóa được đồng bộ hóa là một công cụ mạnh mẽ để kiểm soát việc truy cập dữ liệu đồng thời trong các ứng dụng Java. Khi được sử dụng đúng cách, nó có thể giúp đảm bảo tính toàn vẹn dữ liệu và cải thiện hiệu suất.

Ví dụ về việc sử dụng

1. Khối đồng bộ

public class Counter {
  private int count = 0;

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

  public void increment() {
    synchronized (this) {
      count++;
    }
  }
}
Có hai khối mã ở đây truy cập vào bộ đếm. Đơn giản nhất trong số này là phương thức get , phương thức này chỉ đọc giá trị. Thoạt nhìn, phương thức tăng dường như chỉ chứa một dòng mã. Nhưng hãy nhớ rằng thao tác tăng phải đọc giá trị hiện tại, thêm một giá trị vào đó và ghi giá trị mới vào bộ nhớ. Nói cách khác, có ba thao tác phụ mà chúng tôi muốn thực hiện mà không bị gián đoạn bởi các luồng khác. Ví dụ: đặt nó ở phía bên kia hoặc thực hiện thao tác tăng dần nguyên tử . Khi chúng tôi đặt tiền tố vào hai khối mã bằng từ khóa được đồng bộ hóa , điều quan trọng cần lưu ý là chúng tôi cũng đánh dấu chúng là được đồng bộ hóa cho một đối tượng cụ thể , như được hiển thị trong ví dụ của chúng tôi. Điều này có nghĩa là nếu chúng ta có nhiều đối tượng Counter thì các luồng khác nhau có thể cập nhật các bộ đếm khác nhau đó cùng một lúc. Nhưng hai luồng không thể chạy đồng thời các khối được đồng bộ hóa trên cùng một phiên bản Counter .

2. Phương pháp đồng bộ

public class SynchronizedCounter {
    private int c = 0;

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

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

    public synchronized int value() {
        return c;
    }
}
Nếu count là một phiên bản của SynchronizedCounter thì việc đồng bộ hóa các phương thức này có hai tác dụng:
  • Đầu tiên, hai lệnh gọi đến các phương thức được đồng bộ hóa trên cùng một đối tượng không thể xen kẽ. Khi một luồng thực thi một phương thức được đồng bộ hóa trên một đối tượng, tất cả các luồng khác gọi các phương thức được đồng bộ hóa trên cùng một khối của đối tượng sẽ tạm dừng cho đến khi luồng đầu tiên hoàn thành công việc trên đối tượng.

  • Thứ hai, khi phương thức được đồng bộ hóa thoát, nó sẽ tự động đặt giá trị thành “xảy ra trước” trong bất kỳ lệnh gọi tiếp theo nào tới phương thức được đồng bộ hóa trên cùng một đối tượng. Điều này đảm bảo rằng những thay đổi về trạng thái của đối tượng được hiển thị cho tất cả các luồng.

Hãy nhớ rằng việc biết lý do, cách thức và thời điểm sử dụng đồng bộ hóa cũng như các công cụ sửa đổi khác đi kèm với kinh nghiệm và kinh nghiệm đi kèm với thời gian.

Xử lý tệp trong Java

Nguồn: Usemynotes Nội dung của bài đăng này là về xử lý tệp trong Java. Bạn sẽ làm quen với các thao tác xử lý tệp, các phương thức của lớp Tệp và các loại luồng. Nghỉ giải lao #171.  Cách sử dụng từ khóa được đồng bộ hóa.  Xử lý tệp trong Java - 2Làm việc với các tập tin là một phần không thể thiếu của bất kỳ ngôn ngữ lập trình nào. Bằng cách sử dụng các tập tin, một chương trình có thể lưu trữ dữ liệu trên thiết bị lưu trữ. Việc thực hiện nhiều hành động khác nhau trên một tệp, chẳng hạn như đọc hoặc ghi, yêu cầu phải xử lý tệp. Xử lý tệp được định nghĩa là đọc từ tệp và ghi vào tệp. Để tạo một đối tượng tệp và xử lý các định dạng tệp khác nhau, chúng ta có thể sử dụng lớp File từ gói java.io. Nếu muốn sử dụng lớp File, chúng ta cần tạo một đối tượng của lớp File và chỉ định tên hoặc đường dẫn của tệp. Sử dụng lớp này, chúng ta có thể truy cập siêu dữ liệu của tệp như tên tệp, kích thước tệp, quyền, loại tệp, v.v.
// 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");
}
}
Để nhập lớp File , bạn cũng có thể sử dụng import java.io.File thay vì import java.io.* . Bây giờ chúng ta hãy tìm hiểu về các luồng vì Java sử dụng các luồng để thực hiện các thao tác vào/ra (I/O) trên một tệp.

Chuỗi trong Java là gì?

Luồng là một chuỗi dữ liệu. Nó cũng có thể được định nghĩa là một chuỗi byte. Một luồng có thể được sử dụng để thể hiện nguồn đầu vào hoặc đích. Nguồn và đích có thể là các tệp trên đĩa, mảng, tệp văn bản, v.v. Luồng đầu vào đọc hoặc lấy dữ liệu từ nguồn và luồng đầu ra ghi dữ liệu vào đích. Có hai loại luồng:

Luồng byte

Luồng Byte được sử dụng để thực hiện các thao tác đọc và ghi trên dữ liệu byte. Quá trình xử lý tệp luồng byte được định nghĩa là thực hiện đầu vào bằng dữ liệu byte. Có nhiều lớp liên quan đến luồng byte, nhưng các lớp được sử dụng phổ biến nhất là FileInputStreamFileOutputStream .
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();
 }
}
Trong ví dụ trên, chúng ta đang đọc dữ liệu từ tệp nguồn và ghi dữ liệu vào đích. -1 cho biết phần cuối của tập tin. Vì vậy việc đọc từ file nguồn sẽ dừng khi -1 xuất hiện.

Luồng ký tự

Luồng ký tự được sử dụng để thực hiện các thao tác đọc và ghi trên dữ liệu ký tự. Quá trình xử lý một file có luồng ký tự là quá trình thực thi dữ liệu đầu vào bằng các ký tự. Có nhiều lớp luồng ký tự có sẵn, nhưng các lớp được sử dụng phổ biến nhất bao gồm FileWriterFileReader . Bây giờ hãy thảo luận về một số phương thức của lớp File .

Các phương thức của lớp File trong Java

có thể đọc()

Phương thức lớp tệp này kiểm tra xem tệp có thể đọc được hay không và trả về giá trị Boolean, nghĩa là đúng hoặc sai .

có thể viết()

Đây là một phương thức lớp tệp để kiểm tra xem một tệp có thể ghi được hay không và trả về giá trị boolean, tức là đúng hay sai.

tồn tại()

Đây là một phương thức lớp tệp được sử dụng để kiểm tra sự tồn tại của một tệp nhất định và trả về giá trị boolean.

tạoNewFile()

Khi chúng ta muốn tạo một tệp trống mới, hãy sử dụng phương thức lớp tệp này. Nó trả về một giá trị boolean.

xóa bỏ()

Đây là một phương thức lớp tệp được sử dụng để xóa một tệp và trả về giá trị boolean.

getAbsolutePath()

Phương thức này được sử dụng để trả về đường dẫn tuyệt đối của tệp. getName() Đây là phương thức được sử dụng để trả về giá trị chuỗi là tên của tệp.

danh sách()

Nó trả về một chuỗi các chuỗi đại diện cho tất cả các tệp trong thư mục.

chiều dài()

Phương thức lớp tệp này trả về kích thước tệp theo byte.

mkdir()

Đây là một phương thức lớp tệp được sử dụng để tạo một thư mục mới. Chúng ta hãy xem các thao tác tệp khác nhau có sẵn trong Java và cách sử dụng chúng.

Các thao tác với tệp trong Java là gì?

Khi xử lý tệp Java, chúng ta có thể thực hiện các thao tác sau trên một tệp:
  • Tạo một tập tin
  • Ghi dữ liệu vào một tập tin
  • Đọc dữ liệu từ một tập tin
  • Xóa một tập tin
  • Lấy thông tin về một tập tin
  • Tạo một tập tin
Trong Java, chúng ta có thể tạo một tệp bằng phương thức createNewFile() của lớp File . Phương thức này trả về true nếu tệp được tạo, ngược lại trả về false nếu tệp đã tồn tại.
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.");
 }
}

Ghi dữ liệu vào một tập tin

Thao tác ghi vào tệp có nghĩa là lưu trữ dữ liệu trong một tệp. Để thực hiện các thao tác ghi trên một tệp, chúng ta sử dụng phương thức write() cùng với lớp FileWriter . Để đóng luồng và nhận tài nguyên được phân bổ, chúng ta phải sử dụng phương thức 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();
   }
}

Đọc từ một tập tin

Hoạt động đọc có nghĩa là truy cập hoặc truy xuất dữ liệu được lưu trữ trong một tệp. Để thực hiện thao tác ghi trên một tệp, chúng ta sẽ sử dụng lớp Scanner cùng với các phương thức hasNextLine()nextLine() để lấy dữ liệu từ tệp. Để đóng một luồng, chúng ta phải sử dụng phương thức 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();
   }
}

Xóa một tập tin

Khi xử lý các file Java, chúng ta có thể xóa một file bằng phương thức delete() của lớp File . Không cần phải đóng tệp bằng hàm close() vì các lớp FileWriterScanner không được sử dụng để xóa tệp .
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.");
   }
}

Lấy thông tin về một tập tin

Có một số phương pháp trong Java để lấy thông tin về một tệp. Chúng đã được đề cập trước đó trong các phương thức của lớp tệp.
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());
  }
}
Chúng ta hãy xem cách một chương trình Java hoạt động để xác định xem một số là số chẵn hay số lẻ bằng cách sử dụng luồng mảng byte trong khi xử lý các tệp Java. Để viết chương trình này, chúng ta sẽ sử dụng lớp ByteArrayInputStream từ gói java.io. Lớp này chứa một bộ đệm được sử dụng để đọc một mảng byte dưới dạng luồng đầu vào. Dưới đây là đoạn mã để kiểm tra xem số chẵn hay số lẻ.
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.");
     }
   }
}
Tôi hy vọng thông tin được trình bày ở đây hữu ích cho bạn. Để hiểu rõ hơn về cách làm việc với các tệp trong Java, bạn nên thử tự mình triển khai tất cả các tệp và phương thức thao tác.
Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION