Scala Future块无法访问外部传入的url参数问题求助
问题分析与解决
你的代码中并非url参数无法访问,而是Future的任务未被正常调度执行,或在IO环节阻塞。以下是具体原因和解决方案:
1. Scala App特质的初始化冲突
App特质依赖DelayedInit机制延迟初始化代码,这会和Future的调度逻辑产生冲突,导致提交的Future任务无法被执行池调度。
解决方法:改用显式main方法替代App特质
package exercises.ch4 import scala.concurrent.ExecutionContext.Implicits.global import scala.concurrent.duration.DurationInt import scala.concurrent.{Await, Future} import scala.io.Source import scala.util.{Failure, Success} object Ex1 { def main(args: Array[String]): Unit = { val mainUrl = "https://example-files.online-convert.com/document/txt/example.txt" def getWebPage(url: String): Future[String] = Future { println(s"${Thread.currentThread().getName} : inside the future. Url is: ${url}") val source = Source.fromURL(url) println(s"printing from the middle") val result = try source.mkString finally source.close() println(s"printing from the future: ${result}") result } println(s"${Thread.currentThread().getName} : outside of the future") val futureResult = getWebPage(mainUrl) futureResult.onComplete { case Success(value) => println(s"printing from onComplete: ${value}") case Failure(exception) => println(exception) } Await.ready(futureResult, 5.seconds) } }
2. 默认线程池资源不足
ExecutionContext.Implicits.global默认使用ForkJoinPool,线程数等于CPU核心数。如果阻塞IO操作(如Source.fromURL)占用了所有线程,会导致任务调度停滞。
解决方法:自定义更大的线程池
import java.util.concurrent.Executors import scala.concurrent.ExecutionContext // 在main方法内定义自定义ExecutionContext implicit val ec: ExecutionContext = ExecutionContext.fromExecutor(Executors.newFixedThreadPool(10))
3. IO操作无超时导致阻塞
Source.fromURL默认没有超时设置,若遇到DNS解析失败、网络代理问题或目标服务器无响应,会一直阻塞线程,导致后续代码无法执行。
解决方法:给IO操作添加超时限制
def getWebPage(url: String): Future[String] = Future { println(s"${Thread.currentThread().getName} : inside the future. Url is: ${url}") val urlObj = new URL(url) val connection = urlObj.openConnection() connection.setConnectTimeout(3000) // 连接超时3秒 connection.setReadTimeout(3000) // 读取超时3秒 val source = Source.fromInputStream(connection.getInputStream) println(s"printing from the middle") val result = try source.mkString finally source.close() println(s"printing from the future: ${result}") result }
内容的提问来源于stack exchange,提问作者maiooc
相关产品推荐
相关产品推荐

