Java IO inputstream blocs en lisant la sortie standard et l'erreur standard d'un programme C externe

StackOverflow https://stackoverflow.com/questions/1105569

  •  12-09-2019
  •  | 
  •  

Question

J'ai posté la même question il y a quelques jours ( Java sortie standard de lecture d'un programme externe à l'aide inputstream), et je l'ai trouvé quelques excellents conseils pour faire face à un bloc lors de la lecture (while (is.read ())! = -1)), mais je ne peux toujours pas résoudre le problème.

Après avoir lu les réponses à cette question similaire,

Java InputStream bloquante (En particulier, la réponse affichée par Guss),

Je commence à croire que le bouclage d'un flux d'entrée en utilisant is.read ()! = -1 condition ne fonctionne pas si le programme est interactif (qui est elle prend plusieurs entrées de l'utilisateur et présentent des sorties supplémentaires sur les entrées suivantes et le programme sort uniquement lorsqu'une commande de sortie explicite est donnée). Je reconnais que je ne sais pas beaucoup sur le multi-threading, mais je pense que ce que j'ai besoin est un mécanisme pour mettre en pause rapidement les fils de flux d'entrée (un pour chaque stdout, stderr) lorsqu'une entrée utilisateur est nécessaire, et reprendre une fois que l'entrée est prévus pour empêcher un bloc. Ce qui suit est mon code actuel qui connaît un bloc sur la ligne indiquée:

EGMProcess egm = new EGMProcess(new String[]{directory + "/egm", "-o",
                "CasinoA", "-v", "VendorA", "-s", "localhost:8080/gls/MessageRobot.action ",
                "-E", "glss_env_cert.pem", "-S", "glss_sig_cert.pem", "-C", "glsc_sig_cert.pem",
                "-d", "config", "-L", "config/log.txt", "-H", "GLSA-SampleHost"}, new String[]{"PATH=${PATH}"}, directory);

    egm.execute();

    BufferedReader stdout = new BufferedReader(new InputStreamReader(egm.getInputStream()));
    BufferedReader stderr = new BufferedReader(new InputStreamReader(egm.getErrorStream()));

    EGMStreamGobbler stdoutprocessor = new EGMStreamGobbler(stdout, egm);
    EGMStreamGobbler stderrprocessor = new EGMStreamGobbler(stderr, egm);

    BufferedWriter stdin = new BufferedWriter(new OutputStreamWriter(egm.getOutputStream()));


    stderrprocessor.run(); //<-- the block occurs here!
    stdoutprocessor.run();


    //EGM/Agent test cases


        //check bootstrap menu
        if(!checkSimpleResult("******** EGM Bootstrap Menu **********", egm))
        {
            String stdoutdump = egm.getStdOut();
            egm.cleanup();
            throw new Exception("can't find '******** EGM Bootstrap Menu **********'" +
                "in the stdout" + "\nStandard Output Dump:\n" + stdoutdump);
        }

        //select bootstrap
        stdin.write("1".toCharArray());
        stdin.flush();

        if(!checkSimpleResult("Enter port to receive msgs pushed from server ('0' for no push support)", egm)){
            String stdoutdump = egm.getStdOut();
            egm.cleanup();
            throw new Exception("can't find 'Enter port to receive msgs pushed from server ('0' for no push support)'" +
                    "in the stdout" + "\nStandard Output Dump:\n" + stdoutdump);
        }

...

public class EGMStreamGobbler implements Runnable{

private BufferedReader instream; private EGMProcess egm; public EGMStreamGobbler(BufferedReader isr, EGMProcess aEGM) { instream = isr; egm = aEGM; } public void run() { try{ int c; while((c = instream.read()) != 1) { egm.processStdOutStream((char)c); } } catch(IOException e) { e.printStackTrace(); } }

}

Je présente mes excuses pour la longueur du code, mais mes questions sont,

1) Est-il possible de contrôler le processus de prise en InputStreams (stdout, stderr) sans utiliser read ()? Ou suis-je juste mal mettre en œuvre cette?

2) Est-ce multi-threading la bonne stratégie pour le développement du processus de prise en InputStreams et écriture d'une sortie?

PS: si quelqu'un peut fournir un problème similaire avec une solution, cela me aidera beaucoup

Était-ce utile?

La solution

au lieu de

stderrprocessor.run(); //<-- the block occurs here!
stdoutprocessor.run();

Vous devez commencer les discussions:

Thread errThread = new Thread(stderrprocessor);
errThread.setDaemon( true );
errThread.start();

Thread outThread = new Thread(stdoutprocessor);
outThread.setDaemon( true );
outThread.start();

run() est juste une méthode spécifiée dans Runnable. Thread.start() appelle run() sur le Runnable dans une nouvelle Thread.

Autres conseils

  1. Si vous appelez simplement #run () sur un runnable, il ne sera pas exécuté en parallèle. Pour exécuter en parallèle, vous devez frayer un java.lang.Thread, qui exécute la #run () de votre Runnable.
  2. Que ce soit un des blocs de cours d'eau dépend des deux côtés du cours d'eau. Si l'expéditeur ne soit envoie pas de données ou le récepteur ne reçoit pas de données, vous avez une situation de blocage. Si le processeur doit faire quelque chose, alors que le flux est bloqué, vous devez frayer un (autre) thread dans le processeur d'attendre de nouvelles données et d'interrompre le processus de remplacement, lorsque de nouvelles données sont transmises en continu.

D'abord, vous devez lire sur la discussion et Runnable. Vous n'appelez pas Runnable.run () directement, vous configurez Threads de le faire, et commencer les discussions.

Mais le plus important, la présence de trois fils indépendants implique la nécessité d'une conception soignée. Pourquoi 3 fils? Les deux vous venez de commencer, et le principal.

Je suppose que l'idée generall de votre application est d'attendre une sortie pour arriver, l'interpréter et à la suite envoyer une commande à l'application que vous contrôlez?

Donc, votre thread principal doit attendre pour l'un des fils de lecteur de dire « Aha! Qui est intéressant, mieux demander à l'utilisateur ce qu'il veut faire. »

En d'autres termes, vous avez besoin d'un mécanisme de communication entre vos lecteurs et votre graveur. Cela peut être mis en œuvre en utilisant le mécanisme d'événement de Java. Pourtant, plus de lecture que j'ai peur.

est-ce pas pourquoi le nio a été créé?

Je ne sais pas beaucoup sur les canaux dans nio, mais cette réponse peut être utile. Il montre comment lire un fichier en utilisant nio. Peut être utile.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top