Hoe een threadblokkering op socket IO-bewerking onmiddellijk beëindigen?

In de context van Java maak ik een nieuwe thread om netwerkinvoer te lezen wanneer ik een GUI-venster open, en wanneer ik het venster sluit, wil ik de socketbron vrijgeven en de thread onmiddellijk beëindigen. Nu gebruik ik de setSoTimeout-methode, maar ik wil niet wachten op de time-outuitzondering. Kan iemand een suggestie geven? Bedankt!


Antwoord 1, autoriteit 100%

Er zijn (mogelijk) drie manieren om dit te doen:

  • Bellen Socket.close()op de socket sluit de bijbehorende InputStream– en OutputStream-objecten en zorgt ervoor dat alle threads worden geblokkeerd in Socket of (geassocieerde ) stream-bewerkingen die moeten worden gedeblokkeerd. Volgens de javadoc zullen bewerkingen op de socket zelf een veroorzaken SocketException.

  • Bellen Thread.interrupt()zal (onder bepaalde omstandigheden die niet zijn gespecificeerd) een blokkerende I/O-bewerking onderbreken, waardoor een InterruptedIOException.

    Let op het voorbehoud. Blijkbaar werkt de “interrupt()”-aanpak niet op de “meeste” moderne Java-platforms. (Als iemand anders de tijd en de neiging had, zouden ze mogelijk de omstandigheden kunnen onderzoeken waarin deze aanpak werkt. Het enkele feit dat het gedrag platformspecifiek is, zou echter voldoende moeten zijn om te zeggen dat je het alleen moet gebruiken als je alleen je applicatie nodig hebt om op een specifiek platform te werken. Op dat moment kunt u het gemakkelijk zelf ‘proberen’.)

  • Een mogelijke derde manier om dit te doen is door Socket.shutdownInput()en/of Socket.shutdownOutput(). De javadocs zeggen niet expliciet wat er gebeurt met lees- en/of schrijfbewerkingen die momenteel zijn geblokkeerd, maar het is niet onredelijk om te denken dat ze de blokkering zullen opheffen en een uitzondering zullen genereren. Als de javadoc echter niet zegt wat er gebeurt, moet worden aangenomen dat het gedrag platformspecifiek is.


Antwoord 2, autoriteit 30%

Ik weet dat deze vraag oud is, maar aangezien niemand het “mysterie” van Thread.interrupt()op “moderne platforms” lijkt te hebben opgelost, heb ik wat onderzoek gedaan.

Dit is getest op Java 8 op Windows7 (64-bit) (maar zal mogelijk ook gelden voor andere platforms).

Het aanroepen van Thread.interrupt()geeft geeneen InterruptedIOException
Wat er gebeurt, is dat de methode InputStream.read()retourneert met -1en Thread.interrupted()-flag is ingesteld.

Dus het volgende kan worden beschouwd als een ‘gecorrigeerde’ read() die InterruptedIOExceptiongenereert:

static final int read(Socket socket, byte[] inData) 
    throws SocketTimeoutException, // if setSoTimeout() was set and read timed out
           InterruptedIOException, // if thread interrupted
           IOException             // other erors
{
    InputStream in = socket.getInputStream();
    int readBytes = in.read( inData, 0, inData.length);
    if  ( Thread.interrupted() )
    {
        throw new InterruptedIOException( "Thread interrupted during socket read");
    }
    return readBytes;
}

Other episodes