blocking read - Que fait InputStream.available()en Java?



import fileinputstream (5)

Que fait InputStream.available() en Java ? J'ai lu la documentation, mais je n'arrive toujours pas à la comprendre.

Le doc dit:

Renvoie le nombre d'octets pouvant être lus (ou ignorés) à partir de ce flux d'entrée sans que l'appelant suivant ne bloque une méthode pour ce flux d'entrée. Le prochain appelant peut être le même thread ou un autre thread.

La méthode disponible pour la classe InputStream renvoie toujours 0.

Que veulent-ils dire par blocage ? Est-ce que cela signifie simplement un appel synchronisé?

Et surtout, quel est le but de la méthode available() ?


Answers

Le blocage ne concerne pas le threading ou la synchronisation ici. Au lieu de cela, cela concerne le blocage des entrées / sorties (voir this pour plus d’informations). Si vous émettez une demande de lecture et que le canal n'est pas disponible, un appel bloquant attendra (ou bloquera) que les données soient disponibles (ou si le canal est fermé, lève une exception, etc.).

Alors, pourquoi utiliser available() ? Vous pouvez donc déterminer le nombre d'octets à lire ou déterminer si vous allez bloquer.

Notez que Java dispose également de capacités d’E / S non bloquantes. Voir here pour plus de détails


Considérez si vous écrivez un logiciel TRÈS BADLY .. et que vous écrivez un système d'exploitation.

Ce système d'exploitation prend la saisie au clavier parmi d'autres choses.

Vous demandez donc à votre système d’exploiter une entrée au clavier, mais il n’ya aucune touche enfoncée et aucune dans la mémoire tampon. Whole OS accrochera alors jusqu'à ce qu'il obtienne une entrée au clavier.

Si vous optez pour «regarder devant», vous demandez si la base de connaissances contient des caractères AVANT de passer l’appel. Vous obtenez la réponse NON, alors votre système d'exploitation va et fait autre chose.

C’est POURQUOI vous devriez vous en soucier. Maintenant, si vous multipliez ensuite cette action par une autre tâche potentiellement bloquante, vous pouvez voir pourquoi «regarder de l’avant» est essentiel.

Parce qu’il s’applique également à OUTPUT: Une mémoire sur une interface de lecteur de disque peut également injecter des données dans le lecteur de disque plus rapidement qu’elle ne peut les traiter. Si vous ne savez pas que la mémoire tampon du lecteur est saturée de données, la tâche sera bloquée jusqu'à ce que la mémoire tampon puisse accepter plus de données.

Cela met également en évidence le non-sens de "il y a très peu d'utilisations utiles".


Une des utilisations pratiques possibles de available() est de l'utiliser pour choisir une longueur de tampon raisonnable.

static final int LEN = 4096;

long copy(InputStream in, OutputStream out) throws IOException {
    int count = 0L;
    int avl = in.available();
    if (avl == 0) {
        // 0 returned without IOException? possibly mean eof?
        return 0L;
    }
    //byte[] buf = new byte[avl == 0 ? LEN : Math.min(avl, LEN)];
    byte[] buf = new byte[Math.min(avl, LEN)];
    for (int len; (len = in.read(buf)) != -1; count+= len) {
        out.write(buf, 0, len);
    }
    return count;
}

Le document dit:

Retourne: une estimation du nombre d'octets pouvant être lus (ou ignorés) à partir de ce flux d'entrée sans blocage ou 0 lorsqu'il atteint la fin du flux d'entrée .

Et

L'implémentation de cette méthode par une sous-classe peut choisir de IOException une IOException si ce flux d'entrée a été fermé en appelant la méthode close() .

METTRE À JOUR

Je sais déjà que l'idée n'est pas recommandée. Je connaissais ce risque avant même que le doc du JDK ne le prévienne. (Une fois, j’ai essayé d’attribuer un tampon à partir de FileInputStream de quelques Go FileInputStream .)

JDK8/InputStream#available

Il n'est jamais correct d'utiliser la valeur de retour de cette méthode pour allouer un tampon destiné à contenir toutes les données de ce flux.

JDK5/InputStream#availabe

Mais, en programmation, il ne devrait pas y avoir de code never ou always wrong . C'est ce que je crois.


Dans InputStreams, les appels read() sont dits "bloquants" les appels de méthode. Cela signifie que si aucune donnée n'est disponible au moment de l'appel de la méthode, celle-ci attendra que les données soient disponibles.

La méthode available() vous indique le nombre d'octets pouvant être lus jusqu'à ce que l'appel read() bloque le flux d'exécution de votre programme. Sur la plupart des flux d'entrée, tous les appels à read() sont bloquants, c'est pourquoi available renvoie 0 par défaut.

Cependant, sur certains flux (tels que BufferedInputStream , qui ont un tampon interne), certains octets sont lus et conservés en mémoire, ce qui vous permet de les lire sans bloquer le flux du programme. Dans ce cas, la méthode available() vous indique le nombre d'octets conservés dans le tampon.


Je sais que deux threads ne peuvent pas entrer dans le bloc Synchroniser en même temps

Deux threads ne peuvent pas entrer deux fois un bloc synchronisé sur le même objet. Cela signifie que deux threads peuvent entrer dans le même bloc sur différents objets. Cette confusion peut conduire à un code comme celui-ci.

private Integer i = 0;

synchronized(i) {
   i++;
}

Cela ne se comportera pas comme prévu car il pourrait être verrouillé sur un objet différent à chaque fois.

si cela est vrai que Comment this atomic.incrementAndGet () fonctionne sans Synchronize ?? et est thread safe?

Oui. Il n'utilise pas de verrouillage pour assurer la sécurité du filetage.

Si vous voulez savoir comment ils fonctionnent plus en détail, vous pouvez lire le code pour eux.

Et quelle est la différence entre la lecture interne et l'écriture de Variable Volatile / Variable Atomique?

La classe Atomic utilise des champs volatils . Il n'y a pas de différence sur le terrain. La différence est les opérations effectuées. Les classes Atomic utilisent les opérations CompareAndSwap ou CAS.

J'ai lu dans un article que le fil a une copie locale des variables qu'est-ce que c'est ??

Je ne peux que supposer que cela fait référence au fait que chaque CPU a sa propre vue en mémoire cache qui peut être différente de toutes les autres CPU. Pour garantir que votre UC dispose d'une vue cohérente des données, vous devez utiliser des techniques de sécurité des threads.

C'est seulement un problème quand la mémoire est partagée qu'au moins un thread le met à jour.





java blocking inputstream