[SPARK-4195][Core]retry to fetch blocks's result when fetchfailed's reason is connection timeout

when there are many executors in a application(example:1000),Connection timeout often occure.
Exception is:
WARN nio.SendingConnection: Error finishing connection 
java.net.ConnectException: Connection timed out
        at sun.nio.ch.SocketChannelImpl.checkConnect(Native Method)
        at sun.nio.ch.SocketChannelImpl.finishConnect(SocketChannelImpl.java:739)
        at org.apache.spark.network.nio.SendingConnection.finishConnect(Connection.scala:342)
        at org.apache.spark.network.nio.ConnectionManager$$anon$11.run(ConnectionManager.scala:273)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
        at java.lang.Thread.run(Thread.java:744)

that will make driver as these executors are lost, but in fact these executors are alive. so add retry mechanism to reduce the probability of the occurrence of this problem. @rxin
We don't need mutability for this (or for `isRetry`):

```scala
val failedCount = blockFailedCounts.synchronized {
   val newFailedCount = blockFailedCounts(blockIds).getOrElse(0) + 1
   blockFailedCounts(blockIds) = newFailedCount
   newFailedCount
}
if (failedCount >= maxRetryNum) {
  blockFailedCounts.synchronized {
    blockFailedCounts -= blockIds
  }
  blockIds.foreach { blockId =>
    listener.onBlockFetchFailure(blockId, connectExcpt)
  }
} else {
  fetchBlocks(hostName, port, blockIds, listener)
}
```