JavaRush /Java Blog /Random-IT /Apprezza il tempo trascorso con gli streaming
Andrei
Livello 2

Apprezza il tempo trascorso con gli streaming

Pubblicato nel gruppo Random-IT

Prefazione. Zio Petya

Quindi, diciamo che volessimo riempire una bottiglia d'acqua. Sono disponibili una bottiglia e un rubinetto dell'acqua di zio Petya. Oggi zio Petya ha fatto installare un nuovo rubinetto e continuava a lodarne la bellezza. Prima utilizzava solo un rubinetto vecchio e intasato, quindi le file all'imbottigliamento erano enormi. Dopo aver armeggiato un po', si è sentito il rumore dell'acqua che si riempiva dalla direzione della fuoriuscita, dopo 2 minuti la bottiglia è ancora in fase di riempimento, la solita coda si è formata dietro di noi, e l'immagine nella mia testa è di quanto sia premuroso lo zio Petya seleziona solo le migliori molecole di H2O nella nostra bottiglia. Lo zio Petya, allenato dalla vita, calma quelli particolarmente aggressivi e promette di finire il più rapidamente possibile. Finita la bottiglia, prende la successiva e apre la solita pressione, che non rivela tutte le potenzialità del nuovo rubinetto. Le persone non sono felici... Apprezzare il tempo con i flussi - 1

Teoria

Il multithreading è la capacità di una piattaforma di creare più thread all'interno di un singolo processo. Creare ed eseguire un thread è molto più semplice che creare un processo, quindi se è necessario implementare più azioni parallele in un programma, vengono utilizzati thread aggiuntivi. Nella JVM, qualsiasi programma viene eseguito nel thread principale e il resto viene avviato da esso. All'interno dello stesso processo, i thread sono in grado di scambiare dati tra loro. Quando si avvia un nuovo thread, è possibile dichiararlo come thread utente utilizzando il metodo
setDaemon(true);
tali thread termineranno automaticamente se non rimangono altri thread in esecuzione. I thread hanno priorità di lavoro (la scelta della priorità non garantisce che il thread con la priorità più alta finirà più velocemente del thread con la priorità più bassa).
  • MIN_PRIORITY
  • NORM_PRIORITY (predefinito)
  • MAX_PRIORITÀ
Metodi di base quando si lavora con i flussi:
  • run()– esegue il thread
  • start()– inizia una discussione
  • getName()– restituisce il nome del thread
  • setName()– specifica il nome dello stream
  • wait()– metodo ereditato, il thread attende che il metodo venga chiamato notify()da un altro thread
  • notify()– metodo ereditato, riprende un thread precedentemente interrotto
  • notifyAll()– metodo ereditato, riprende i thread precedentemente interrotti
  • sleep()– mette in pausa lo streaming per un tempo specificato
  • join()– attende il completamento del thread
  • interrupt()– interrompe l'esecuzione del thread
Puoi trovare altri metodi qui. È tempo di pensare a nuovi thread se il tuo programma ha:
  • Accesso alla rete
  • Accesso al file system
  • GUI

Classe del thread

I thread in Java sono rappresentati come una classe Threade i suoi discendenti. L'esempio seguente è una semplice implementazione della classe stream.
import static java.lang.System.out;

public class ExampleThread extends Thread{

    public static void main(String[] args) {
        out.println("Основной поток");
        new ExampleThread().start();
    }

    @Override
    public void run() {
        out.println("Новый поток");
    }
}
Di conseguenza otteniamo
Основной поток
Новый поток
Qui creiamo la nostra classe e la rendiamo discendente della classe Thread, dopodiché scriviamo il metodo main() per avviare il thread principale e sovrascrivere il metodo run()della classe Thread. Ora, dopo aver creato un'istanza della nostra classe ed eseguito il suo metodo ereditato, start()lanceremo un nuovo thread in cui verrà eseguito tutto ciò che è descritto nel corpo del metodo run(). Sembra complicato, ma guardando il codice di esempio dovrebbe essere tutto chiaro.

Interfaccia eseguibile

Oracle suggerisce anche di implementare l'interfaccia per iniziare un nuovo thread Runnable, il che ci dà maggiore flessibilità di progettazione rispetto all'unica ereditarietà disponibile nell'esempio precedente (se guardi il sorgente della classe Threadpuoi vedere che implementa anche l'interfaccia Runnable). Usiamo il metodo consigliato per creare un nuovo thread.
import static java.lang.System.out;

public class ExampleRunnable implements Runnable {

    public static void main(String[] args) {
        out.println("Основной поток");
        new Thread(new ExampleRunnable()).start();
    }

    @Override
    public void run() {
        out.println("Новый поток");
    }
}
Di conseguenza otteniamo
Основной поток
Новый поток
Gli esempi sono molto simili, perché Durante la scrittura del codice, abbiamo dovuto implementare un metodo astratto run()descritto nell'interfaccia Runnable. Avviare un nuovo thread è leggermente diverso. Abbiamo creato un'istanza della classe Threadpassando un riferimento a un'istanza della nostra implementazione dell'interfaccia come parametro Runnable. È questo approccio che consente di creare nuovi thread senza ereditare direttamente la classe Thread.

Operazioni lunghe

L'esempio seguente mostrerà chiaramente i vantaggi dell'utilizzo di più thread. Diciamo che abbiamo un compito semplice che richiede diversi calcoli lunghi, prima di questo articolo lo avremmo risolto in un metodo, main()magari suddividendolo in metodi separati per facilità di percezione, magari anche in classi, ma l'essenza sarebbe la stessa. Tutte le operazioni verrebbero eseguite in sequenza una dopo l'altra. Simuliamo calcoli pesanti e misuriamo il loro tempo di esecuzione.
public class ComputeClass {

    public static void main(String[] args) {
        // Узнаем стартовое время программы
        long startTime = System.currentTimeMillis();

        // Определяем долгосрочные операции
        for(double i = 0; i < 999999999; i++){
        }
        System.out.println("complete 1");
        for(double i = 0; i < 999999999; i++){
        }
        System.out.println("complete 2");
        for(double i = 0; i < 999999999; i++){
        }
        System.out.println("complete 3");

        //Вычисляем и выводим время выполнения программы
        long timeSpent = System.currentTimeMillis() - startTime;
        System.out.println("программа выполнялась " + timeSpent + " миллисекунд");
    }
}
Di conseguenza otteniamo
complete 1
complete 2
complete 3
программа выполнялась 9885 миллисекунд
Il tempo di esecuzione lascia molto a desiderare, e per tutto questo tempo stiamo guardando una schermata di output vuota, e la situazione è molto simile alla storia di Zio Petya, solo che ora nel suo ruolo noi sviluppatori non ne abbiamo approfittato tutte le funzionalità dei dispositivi moderni. Miglioreremo.
public class ComputeClass {

    public static void main(String[] args) {
        // Узнаем стартовое время программы
        long startTime = System.currentTimeMillis();

        // Определяем долгосрочные операции
        new MyThread(1).start();
        new MyThread(2).start();
        for(double i = 0; i < 999999999; i++){
        }
        System.out.println("complete 3");

        //Вычисляем и выводим время выполнения программы
        long timeSpent = System.currentTimeMillis() - startTime;
        System.out.println("программа выполнялась " + timeSpent + " миллисекунд");
    }
}

class MyThread extends Thread{
int n;

MyThread(int n){
    this.n = n;
}

    @Override
    public void run() {
        for(double i = 0; i < 999999999; i++){
        }
        System.out.println("complete " + n);
    }
}
Di conseguenza otteniamo
complete 1
complete 2
complete 3
программа выполнялась 3466 миллисекунд
Il tempo di esecuzione è stato notevolmente ridotto (questo effetto potrebbe non essere ottenuto o addirittura aumentare il tempo di esecuzione su processori che non supportano il multithreading). Vale la pena notare che i thread potrebbero finire fuori servizio e se lo sviluppatore ha bisogno della prevedibilità delle azioni, deve implementarla in modo indipendente per un caso specifico.

Gruppi di discussioni

I thread in Java possono essere combinati in gruppi; la classe viene utilizzata per questo ThreadGroup. I gruppi possono includere sia singoli thread che interi gruppi. Ciò può essere comodo se è necessario interrompere i flussi associati, ad esempio, alla rete quando viene persa la connessione. Puoi leggere di più sui gruppi qui. Spero che ora l'argomento ti sia diventato più chiaro e che i tuoi utenti siano contenti.
Apprezzare il tempo con i flussi - 2
Commenti
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION