JavaRush /Blog Java /Random-PL /Przerwa kawowa #171. Jak używać słowa kluczowego synchron...

Przerwa kawowa #171. Jak używać słowa kluczowego synchronized. Obsługa plików w Javie

Opublikowano w grupie Random-PL

Jak używać słowa kluczowego synchronized

Źródło: Medium Dziś dowiesz się w jakich przypadkach i jak poprawnie używać słowa kluczowego synchronized w języku programowania Java. Przerwa kawowa #171.  Jak używać słowa kluczowego synchronized.  Przetwarzanie plików w Javie - 1Modyfikatory to pewne słowa kluczowe obecne w Javie, za pomocą których możemy dokonać zmian w charakterystyce zmiennej, metody lub klasy i ograniczyć jej zakres. Język Java ma dość duży zestaw modyfikatorów. Modyfikatory w Javie dzielą się na dwa typy – modyfikatory dostępu i modyfikatory bez dostępu.

Modyfikatory bez dostępu

Niedostępne modyfikatory dostarczają maszynie JVM informacji o charakterystyce klasy, metody lub zmiennej. W Javie istnieje siedem typów modyfikatorów braku dostępu:
  • finał
  • statyczny
  • abstrakcyjny
  • zsynchronizowane
  • lotny
  • przejściowy
  • rodzinny
W tym artykule przyjrzymy się bliżej słowu kluczowemu synchronized . Najpierw określmy, gdzie i kiedy go używać.

W jakich przypadkach stosuje się synchronizację?

W Javie słowo kluczowe synchronized służy do zapewnienia kontroli dostępu do metody lub bloku kodu. Gdy wątek próbuje wykonać zsynchronizowaną metodę lub blok kodu, musi najpierw uzyskać blokadę. Po otrzymaniu blokady możesz przystąpić do realizacji. Jednak każdy inny wątek próbujący wykonać tę samą zsynchronizowaną metodę lub blok kodu zostanie zablokowany, dopóki pierwszy wątek nie zwolni blokady. Dzięki temu tylko jeden wątek może wykonywać kod w danym momencie, co jest ważne dla zachowania integralności danych. Słowo kluczowe synchronized może być używane zarówno z metodami statycznymi, jak i niestatycznymi, a także z blokami kodu.
  • W przypadku stosowania metod statycznych wszystkie wątki konkurują o tę samą blokadę. Może to mieć wpływ na wydajność, dlatego najlepiej unikać synchronizowania metod statycznych, chyba że jest to absolutnie konieczne.

  • W przypadku użycia z metodami niestatycznymi każda instancja klasy będzie miała własną blokadę, dzięki czemu wiele wątków będzie mogło jednocześnie wykonywać zsynchronizowany kod z różnych instancji. Jest to zazwyczaj preferowane podejście.

  • W przypadku użycia z blokami kodu na obiekcie zostaje nałożona blokada, która jest przekazywana do instrukcji synchronized . Dzięki temu wiele wątków może jednocześnie wykonywać zsynchronizowane bloki kodu z różnych obiektów.

Zatem słowo kluczowe synchronized jest potężnym narzędziem do kontrolowania równoczesnego dostępu do danych w aplikacjach Java. Prawidłowo stosowane może pomóc w zapewnieniu integralności danych i poprawie wydajności.

Przykłady użycia

1. Blok zsynchronizowany

public class Counter {
  private int count = 0;

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

  public void increment() {
    synchronized (this) {
      count++;
    }
  }
}
Znajdują się tu dwa bloki kodu umożliwiające dostęp do licznika. Najprostszą z nich jest metoda get , która po prostu odczytuje wartość. Na pierwszy rzut oka metoda inkrementacji wydaje się zawierać jedną linię kodu. Pamiętaj jednak, że operacja zwiększania musi odczytać bieżącą wartość, dodać do niej jedną i zapisać nową wartość z powrotem do pamięci. Innymi słowy, istnieją trzy podoperacje, które chcemy wykonać bez przerywania przez inne wątki. Na przykład umieszczenie go po drugiej stronie lub uczynienie operacji inkrementacji niepodzielną . Kiedy poprzedzamy dwa bloki kodu słowem kluczowym synchronized , należy pamiętać, że oznaczamy je również jako zsynchronizowane dla konkretnego obiektu , jak pokazano w naszym przykładzie. Oznacza to, że jeśli mamy wiele obiektów Counter , różne wątki mogą jednocześnie aktualizować te różne liczniki. Jednak dwa wątki nie mogą jednocześnie uruchamiać zsynchronizowanych bloków w tej samej instancji Counter .

2. Metoda synchroniczna

public class SynchronizedCounter {
    private int c = 0;

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

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

    public synchronized int value() {
        return c;
    }
}
Jeśli count jest instancją SynchronizedCounter , synchronizacja tych metod ma dwa skutki:
  • Po pierwsze, dwa wywołania metod zsynchronizowanych w tym samym obiekcie nie mogą się przeplatać. Kiedy jeden wątek wykonuje metodę zsynchronizowaną na obiekcie, wszystkie inne wątki wywołujące metody zsynchronizowane w tym samym bloku obiektu wstrzymują się do czasu, aż pierwszy wątek zakończy pracę nad obiektem.

  • Po drugie, gdy metoda synchronized kończy działanie, automatycznie ustawia wartość na „zdarzyło się wcześniej” przy kolejnych wywołaniach metody synchronized na tym samym obiekcie. Dzięki temu zmiany stanu obiektu będą widoczne dla wszystkich wątków.

Pamiętaj, że wiedza o tym, dlaczego, jak i kiedy używać zsynchronizowanych i innych modyfikatorów, przychodzi wraz z doświadczeniem, a doświadczenie przychodzi z czasem.

Obsługa plików w Javie

Źródło: Usemynotes Treść tego wpisu dotyczy przetwarzania plików w Javie. Zapoznasz się z operacjami przetwarzania plików, metodami klasy File i typami strumieni. Przerwa kawowa #171.  Jak używać słowa kluczowego synchronized.  Przetwarzanie plików w Javie - 2Praca z plikami jest integralną częścią każdego języka programowania. Korzystając z plików, program może przechowywać dane na urządzeniu pamięci masowej. Wykonywanie różnych działań na pliku, takich jak odczyt lub zapis, wymaga przetworzenia pliku. Przetwarzanie plików definiuje się jako odczytywanie z pliku i zapisywanie do pliku. Aby utworzyć obiekt plikowy i obsługiwać różne formaty plików, możemy skorzystać z klasy File z pakietu java.io. Jeżeli chcemy skorzystać z klasy File musimy stworzyć obiekt klasy File i podać nazwę pliku lub ścieżkę. Za pomocą tej klasy możemy uzyskać dostęp do metadanych pliku, takich jak nazwa pliku, rozmiar pliku, uprawnienia, typ pliku i tak dalej.
// 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");
}
}
Aby zaimportować klasę File , możesz także użyć import java.io.File zamiast import java.io.* . Dowiedzmy się teraz o wątkach, ponieważ Java używa wątków do wykonywania operacji wejścia/wyjścia (I/O) na pliku.

Co to jest wątek w Javie?

Strumień to sekwencja danych. Można go również zdefiniować jako sekwencję bajtów. Strumienia można użyć do reprezentowania źródła wejściowego lub miejsca docelowego. Źródłem i miejscem docelowym mogą być pliki na dysku, tablice, pliki tekstowe i tak dalej. Strumień wejściowy odczytuje lub pobiera dane ze źródła, a strumień wyjściowy zapisuje dane do miejsca docelowego. Istnieją dwa rodzaje strumieni:

Strumień bajtów

Strumień bajtów służy do wykonywania operacji odczytu i zapisu danych bajtowych. Proces przetwarzania pliku strumienia bajtów definiuje się jako wprowadzanie danych przy użyciu danych bajtowych. Istnieje wiele klas związanych ze strumieniami bajtów, ale najczęściej używanymi klasami są FileInputStream i 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();
 }
}
W powyższym przykładzie odczytujemy dane z pliku źródłowego i zapisujemy je do pliku docelowego. -1 oznacza koniec pliku. Zatem czytanie z pliku źródłowego zostanie zatrzymane, gdy pojawi się -1.

Strumień postaci

Strumień znaków służy do wykonywania operacji odczytu i zapisu danych znakowych. Proces przetwarzania pliku ze strumieniem znaków to proces wykonywania danych wejściowych ze znakami. Dostępnych jest wiele klas strumieni znaków, ale najczęściej używane klasy to FileWriter i FileReader . Omówmy teraz niektóre metody klasy File .

Metody klasy File w Javie

można przeczytać()

Ta metoda klasy pliku sprawdza, czy plik jest czytelny i zwraca wartość logiczną, czyli true lub false .

potrafi pisać()

Jest to metoda klasy pliku, która sprawdza, czy plik nadaje się do zapisu i zwraca wartość logiczną, tj. prawdę lub fałsz.

istnieje()

Jest to metoda klasy pliku używana do sprawdzania istnienia danego pliku i zwracająca wartość logiczną.

utwórzNowyPlik()

Gdy chcemy utworzyć nowy pusty plik, użyj tej metody klasy pliku. Zwraca wartość logiczną.

usuwać()

Jest to metoda klasy pliku używana do usuwania pliku i zwracania wartości logicznej.

getAbsolutePath()

Ta metoda służy do zwracania bezwzględnej ścieżki pliku. getName() Jest to metoda używana do zwracania wartości ciągu znaków będącej nazwą pliku.

lista()

Zwraca tablicę ciągów reprezentujących wszystkie pliki w katalogu.

długość()

Ta metoda klasy pliku zwraca rozmiar pliku w bajtach.

mkdir()

Jest to metoda klasy pliku używana do tworzenia nowego katalogu. Przyjrzyjmy się różnym operacjom na plikach dostępnym w Javie i sposobom ich wykorzystania.

Jakie są operacje na plikach w Javie?

Podczas przetwarzania plików Java możemy wykonać na pliku następujące operacje:
  • Tworzenie pliku
  • Zapisywanie danych do pliku
  • Odczyt danych z pliku
  • Usuwanie pliku
  • Uzyskiwanie informacji o pliku
  • Tworzenie pliku
W Javie plik możemy utworzyć za pomocą metody createNewFile() klasy File . Ta metoda zwraca wartość true , jeśli plik został utworzony, w przeciwnym razie zwraca wartość false , jeśli plik już istnieje.
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.");
 }
}

Zapisywanie danych do pliku

Operacja zapisu do pliku oznacza przechowywanie danych w pliku. Aby wykonać operację zapisu na pliku, używamy metody write() wraz z klasą FileWriter . Aby zamknąć strumień i uzyskać przydzielone zasoby, musimy użyć metody 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();
   }
}

Odczyt z pliku

Operacja odczytu oznacza dostęp lub pobieranie danych przechowywanych w pliku. Aby wykonać operację zapisu na pliku, użyjemy klasy Scanner wraz z metodami hasNextLine() i nextLine() w celu pobrania danych z pliku. Aby zamknąć strumień, musimy użyć metody 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();
   }
}

Usuwanie pliku

Podczas przetwarzania plików Java możemy usunąć plik za pomocą metody usuwania() klasy File . Nie ma potrzeby zamykania pliku za pomocą funkcji close() , ponieważ klasy FileWriter i Scanner nie są używane do usuwania pliku .
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.");
   }
}

Uzyskiwanie informacji o pliku

W Javie istnieje kilka metod uzyskiwania informacji o pliku. Wspomniano już o nich wcześniej w metodach klasy plikowej.
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());
  }
}
Przyjrzyjmy się, jak działa program Java, który określa, czy liczba jest parzysta, czy nieparzysta, za pomocą strumienia tablicy bajtów podczas przetwarzania plików Java. Do napisania tego programu użyjemy klasy ByteArrayInputStream z pakietu java.io. Ta klasa zawiera bufor używany do odczytu tablicy bajtów jako strumienia wejściowego. Poniżej znajduje się kod sprawdzający, czy liczby są parzyste, czy nieparzyste.
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.");
     }
   }
}
Mam nadzieję, że informacje tu przedstawione były dla Ciebie przydatne. Aby lepiej zrozumieć pracę z plikami w Javie, powinieneś spróbować samodzielnie zaimplementować wszystkie metody plików i operacji.
Komentarze
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION