Come utilizzare la parola chiave sincronizzata
Fonte: Medium Oggi imparerai in quali casi e come utilizzare correttamente la parola chiave sincronizzata nel linguaggio di programmazione Java. I modificatori sono alcune parole chiave presenti in Java con l'aiuto delle quali possiamo apportare modifiche alle caratteristiche di una variabile, metodo o classe e limitarne la portata. Il linguaggio Java ha un insieme abbastanza ampio di modificatori. I modificatori in Java sono divisi in due tipi: modificatori di accesso e modificatori non di accesso.Modificatori senza accesso
I modificatori non accessibili forniscono alla JVM informazioni sulle caratteristiche di una classe, metodo o variabile. Esistono sette tipi di modificatori di non accesso in Java:- finale
- statico
- astratto
- sincronizzato
- volatile
- transitorio
- nativo
In quali casi viene utilizzata la sincronizzazione?
In Java, la parola chiave sincronizzata viene utilizzata per fornire il controllo dell'accesso a un metodo o a un blocco di codice. Quando un thread tenta di eseguire un metodo sincronizzato o un blocco di codice, deve prima acquisire un lock. Una volta ricevuto il blocco, puoi iniziare l'esecuzione. Tuttavia, qualsiasi altro thread che tenti di eseguire lo stesso metodo sincronizzato o blocco di codice verrà bloccato finché il primo thread non rilascia il blocco. Ciò garantisce che solo un thread alla volta possa eseguire il codice, il che è importante per mantenere l'integrità dei dati. La parola chiave sincronizzata può essere utilizzata sia con metodi statici che non statici, nonché con blocchi di codice.-
Se utilizzati con metodi statici, tutti i thread competono per lo stesso blocco. Ciò può influire sulle prestazioni, quindi è meglio evitare di sincronizzare i metodi statici a meno che non sia assolutamente necessario.
-
Se utilizzata con metodi non statici, ogni istanza della classe avrà il proprio blocco, quindi più thread possono eseguire simultaneamente codice sincronizzato da istanze diverse. Questo è solitamente l'approccio preferito.
-
Se utilizzato con blocchi di codice, viene acquisito un blocco su un oggetto che viene passato all'istruzione sincronizzata . Ciò consente a più thread di eseguire simultaneamente blocchi di codice sincronizzati da oggetti diversi.
Esempi di utilizzo
1. Blocco sincronizzato
public class Counter {
private int count = 0;
public int getCount() {
synchronized (this) {
return count;
}
}
public void increment() {
synchronized (this) {
count++;
}
}
}
Ci sono due blocchi di codice qui che accedono al contatore. Il più semplice di questi è il metodo get , che legge semplicemente il valore. A prima vista, il metodo di incremento sembra contenere una riga di codice. Ma ricorda che l' operazione di incremento deve leggere il valore corrente, aggiungervi uno e riscrivere il nuovo valore in memoria. In altre parole, ci sono tre operazioni secondarie che vogliamo eseguire senza interruzioni da altri thread. Ad esempio, posizionandolo dall'altra parte o rendendo atomica l' operazione di incremento . Quando anteponiamo due blocchi di codice con la parola chiave sincronizzata , è importante notare che li contrassegniamo anche come sincronizzati per un oggetto specifico , come mostrato nel nostro esempio. Ciò significa che se disponiamo di più oggetti Counter , thread diversi possono aggiornare i diversi contatori contemporaneamente. Ma due thread non possono eseguire contemporaneamente blocchi sincronizzati sulla stessa istanza Counter .
2. Metodo sincronizzato
public class SynchronizedCounter {
private int c = 0;
public synchronized void increment() {
c++;
}
public synchronized void decrement() {
c--;
}
public synchronized int value() {
return c;
}
}
Se count è un'istanza di SynchronizedCounter , la sincronizzazione di questi metodi ha due effetti:
-
Innanzitutto, due chiamate a metodi sincronizzati sullo stesso oggetto non possono intercalarsi. Quando un thread esegue un metodo sincronizzato su un oggetto, tutti gli altri thread che chiamano metodi sincronizzati sullo stesso blocco dell'oggetto vengono sospesi finché il primo thread non termina di lavorare sull'oggetto.
-
In secondo luogo, quando il metodo sincronizzato termina, imposta automaticamente il valore su "accade prima" in tutte le chiamate successive al metodo sincronizzato sullo stesso oggetto. Ciò garantisce che le modifiche allo stato dell'oggetto siano visibili a tutti i thread.
Gestione dei file in Java
Fonte: Usemynotes Il contenuto di questo post riguarda l'elaborazione dei file in Java. Acquisirai familiarità con le operazioni di elaborazione dei file, i metodi della classe File e i tipi di flussi. Lavorare con i file è parte integrante di qualsiasi linguaggio di programmazione. Utilizzando i file, un programma può archiviare dati su un dispositivo di archiviazione. L'esecuzione di varie azioni su un file, come la lettura o la scrittura, richiede l'elaborazione del file. L'elaborazione dei file è definita come la lettura da un file e la scrittura su un file. Per creare un oggetto file e gestire diversi formati di file, possiamo utilizzare la classe File dal pacchetto java.io. Se vogliamo utilizzare la classe File, dobbiamo creare un oggetto della classe File e specificare il nome o il percorso del file. Utilizzando questa classe, possiamo accedere ai metadati del file come nome file, dimensione file, autorizzazioni, tipo di file e così via.// 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");
}
}
Per importare la classe File , puoi anche utilizzare import java.io.File invece di import java.io.* . Ora impariamo a conoscere i thread poiché Java utilizza i thread per eseguire operazioni di input/output (I/O) su un file.
Cos'è un thread in Java?
Il flusso è una sequenza di dati. Può anche essere definito come una sequenza di byte. Un flusso può essere utilizzato per rappresentare un'origine di input o una destinazione. L'origine e la destinazione possono essere file su disco, array, file di testo e così via. Il flusso di input legge o recupera i dati dall'origine e il flusso di output scrive i dati nella destinazione. Esistono due tipi di flussi:Flusso di byte
Un flusso di byte viene utilizzato per eseguire operazioni di lettura e scrittura sui dati byte. Il processo di elaborazione di un file di flusso di byte è definito come l'esecuzione di input utilizzando dati in byte. Esistono molte classi correlate ai flussi di byte, ma le classi più comunemente utilizzate sono FileInputStream e 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();
}
}
Nell'esempio sopra, stiamo leggendo i dati dal file sorgente e scrivendo i dati nella destinazione. -1 indica la fine del file. Quindi la lettura dal file sorgente si interromperà quando appare -1.
Flusso di caratteri
Il flusso di caratteri viene utilizzato per eseguire operazioni di lettura e scrittura sui dati dei caratteri. Il processo di elaborazione di un file con un flusso di caratteri è il processo di esecuzione dei dati di input con caratteri. Sono disponibili molte classi di flussi di caratteri, ma le classi più comunemente utilizzate includono FileWriter e FileReader . Parliamo ora di alcuni metodi della classe File .Metodi della classe File in Java
puòLeggere()
Questo metodo di classe file controlla se il file è leggibile e restituisce un valore booleano, ovvero true o false .puòScrivere()
Questo è un metodo di classe file che controlla se un file è scrivibile e restituisce un valore booleano, ovvero vero o falso.esiste()
Questo è un metodo di classe file utilizzato per verificare l'esistenza di un determinato file e restituisce un valore booleano.creaNuovoFile()
Quando vogliamo creare un nuovo file vuoto, utilizziamo questo metodo di classe file. Restituisce un valore booleano.eliminare()
Questo è un metodo di classe file utilizzato per eliminare un file e restituire un valore booleano.getAbsolutePath()
Questo metodo viene utilizzato per restituire il percorso assoluto di un file. getName() Questo è un metodo utilizzato per restituire un valore stringa che è il nome del file.elenco()
Restituisce un array di stringhe che rappresentano tutti i file nella directory.lunghezza()
Questo metodo di classe file restituisce la dimensione del file in byte.mkdir()
Questo è un metodo di classe file utilizzato per creare una nuova directory. Diamo un'occhiata alle varie operazioni sui file disponibili in Java e come utilizzarle.Cosa sono le operazioni sui file in Java?
Quando elaboriamo file Java, possiamo eseguire le seguenti operazioni su un file:- Creazione di un file
- Scrittura di dati in un file
- Lettura dei dati da un file
- Eliminazione di un file
- Ottenere informazioni su un file
- Creazione di un file
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.");
}
}
Scrittura di dati in un file
Un'operazione di scrittura su un file significa memorizzare i dati in un file. Per eseguire operazioni di scrittura su un file, utilizziamo il metodo write() insieme alla classe FileWriter . Per chiudere uno stream e ottenere le risorse allocate, dobbiamo utilizzare il metodo 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();
}
}
Lettura da un file
Un'operazione di lettura significa accedere o recuperare i dati archiviati in un file. Per eseguire un'operazione di scrittura su un file, utilizzeremo la classe Scanner insieme ai metodi hasNextLine() e nextLine() per recuperare i dati dal file. Per chiudere uno stream dobbiamo utilizzare il metodo 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();
}
}
Eliminazione di un file
Durante l'elaborazione di file Java, possiamo eliminare un file utilizzando il metodo delete() della classe File . Non è necessario chiudere il file utilizzando la funzione close() poiché le classi FileWriter e Scanner non vengono utilizzate per eliminare il 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.");
}
}
Ottenere informazioni su un file
Esistono diversi metodi in Java per ottenere informazioni su un file. Sono già stati menzionati in precedenza nei metodi della classe file.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());
}
}
Diamo un'occhiata a come funziona un programma Java per determinare se un numero è pari o dispari utilizzando un flusso di array di byte durante l'elaborazione dei file Java. Per scrivere questo programma, utilizzeremo la classe ByteArrayInputStream dal pacchetto java.io. Questa classe contiene un buffer utilizzato per leggere una matrice di byte come flusso di input. Di seguito è riportato il codice per verificare se i numeri sono pari o dispari.
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.");
}
}
}
Spero che le informazioni qui presentate ti siano state utili. Per comprendere meglio come lavorare con i file in Java, dovresti provare a implementare tu stesso tutti i metodi relativi ai file e alle operazioni.
GO TO FULL VERSION