Java Reference
In-Depth Information
private
Socket
connection
;
DaytimeThread
(
Socket
connection
)
{
this
.
connection
=
connection
;
}
@Override
public
void
run
()
{
try
{
Writer
out
=
new
OutputStreamWriter
(
connection
.
getOutputStream
());
Date
now
=
new
Date
();
out
.
write
(
now
.
toString
()
+
"\r\n"
);
out
.
flush
();
}
catch
(
IOException
ex
)
{
System
.
err
.
println
(
ex
);
}
finally
{
try
{
connection
.
close
();
}
catch
(
IOException
e
)
{
// ignore;
}
}
}
}
}
Example 9-3
uses try-with-resources to autoclose the server socket. However, it delibā
erately does not use try-with-resources for the client sockets accepted by the server
socket. This is because the client socket escapes from the
try
block into a separate thread.
If you used try-with-resources, the main thread would close the socket as soon as it got
to the end of the
while
loop, likely before the spawned thread had finished using it.
There's actually a denial-of-service attack on this server though. Because
Example 9-3
spawns a new thread for each connection, numerous roughly simultaneous incoming
connections can cause it to spawn an indefinite number of threads. Eventually, the Java
virtual machine will run out of memory and crash. A better approach is to use a fixed
thread pool as described in
Chapter 3
to limit the potential resource usage. Fifty threads
should be plenty.
Example 9-4
shouldn't crash no matter what load it's under. It may
start refusing connections, but it won't crash.
Example 9-4. A daytime server using a thread pool
import
java.io.*
;
import
java.net.*
;
import
java.util.*
;
import
java.util.concurrent.*
;
public
class
PooledDaytimeServer
{