Skip to content

Commit

Permalink
Problem
Browse files Browse the repository at this point in the history
Future.get in com.twitter.util is deprecated.

Solution

Replace Future.get in favor of Await.result.
  • Loading branch information
jcrossley committed Jul 12, 2016
1 parent d9a1cba commit de0b553
Show file tree
Hide file tree
Showing 11 changed files with 211 additions and 211 deletions.
4 changes: 2 additions & 2 deletions web/concurrency.textile
Expand Up @@ -168,7 +168,7 @@ pool-1-thread-2

h2(#Future). Futures

A @Future@ represents an asynchronous computation. You can wrap your computation in a Future and when you need the result, you simply call a blocking @get()@ method on it. An @Executor@ returns a @Future@. If you use the Finagle RPC system, you use @Future@ instances to hold results that might not have arrived yet.
A @Future@ represents an asynchronous computation. You can wrap your computation in a Future and when you need the result, you simply call a blocking @Await.result()@ method on it. An @Executor@ returns a @Future@. If you use the Finagle RPC system, you use @Future@ instances to hold results that might not have arrived yet.

A @FutureTask@ is a Runnable and is designed to be run by an @Executor@

Expand All @@ -183,7 +183,7 @@ executor.execute(future)
Now I need the results so let's block until its done.

<pre>
val blockingResult = future.get()
val blockingResult = Await.result(future)
</pre>

*See Also* <a href="finagle.html">Scala School's Finagle page</a> has plenty of examples of using <code>Future</code>s, including some nice ways to combine them. Effective Scala has opinions about <a href="http://twitter.github.com/effectivescala/#Twitter's standard libraries-Futures">Futures</a> .
Expand Down
44 changes: 22 additions & 22 deletions web/finagle.textile
Expand Up @@ -38,10 +38,10 @@ Finagle uses <code>com.twitter.util.Future</code>[1] to encode delayed operation
<pre>
val myFuture = MySlowService(request) // returns right away
...do other things...
val serviceResult = myFuture.get() // blocks until service "fills in" myFuture
val serviceResult = Await.result(myFuture) // blocks until service "fills in" myFuture
</pre>

In practice, you won't write code that sends a request and then calls <code>myFuture.get</code> a few statements later. A Future has methods to register callbacks to invoke when the value becomes available.
In practice, you won't write code that sends a request and then calls <code>Await.result()/code> a few statements later. A Future has methods to register callbacks to invoke when the value becomes available.

If you've used other asynchronous APIs, you perhaps cringed when you saw the word "callbacks" just now. You might associate them with illegible code flows, functions hiding far from where they're invoked. But Futures can take advantage of Scala's first-class functions to present a more-readable code flow. You can define a simpler handler function in the place where it's invoked.

Expand All @@ -57,39 +57,39 @@ future onSuccess { reply => // when the future gets "filled", use its value
You can play with Futures in the REPL. This is a bad way to learn how you will use them in real code, but can help with understanding the API. When you use the REPL, Promise is a handy class. It's a concrete subclass of the abstract Future class. You can use it to create a Future that has no value yet.

<pre>
scala> import com.twitter.util.{Future,Promise}
import com.twitter.util.{Future, Promise}
scala> import com.twitter.util.{Await, Future,Promise}
import com.twitter.util.{Await, Future, Promise}

scala> val f6 = Future.value(6) // create already-resolved future
f6: com.twitter.util.Future[Int] = com.twitter.util.ConstFuture@c63a8af

scala> f6.get()
scala> Await.result(f6)
res0: Int = 6

scala> val fex = Future.exception(new Exception) // create resolved sad future
fex: com.twitter.util.Future[Nothing] = com.twitter.util.ConstFuture@38ddab20

scala> fex.get()
scala> Await.result(fex)
java.lang.Exception
... stack trace ...

scala> val pr7 = new Promise[Int] // create unresolved future
pr7: com.twitter.util.Promise[Int] = Promise@1994943491(...)

scala> pr7.get()
scala> Await.result(pr7)
...console hangs, waiting for future to resolve...
Ctrl-C
Execution interrupted by signal.

scala> pr7.setValue(7)

scala> pr7.get()
scala> Await.result(pr7)
res1: Int = 7

scala>
</pre>

When you use Futures in real code, you normally don't call <code>get</code>; you use callback functions instead. <code>get</code> is just handy for REPL tinkering.
When you use Futures in real code, you normally don't call <code>Await.result()</code>; you use callback functions instead. <code>Await.result()</code> is just handy for REPL tinkering.

<a name="futsequential">&nbsp;</a>

Expand All @@ -110,8 +110,8 @@ The most important <code>Future</code> combinator is <code>flatMap</code>[2]:
If you have a Future and you want apply an asynchronous API to its value, use <tt>flatMap</tt>. For example, suppose you have a Future[User] and need a Future[Boolean] indicating whether the enclosed User has been banned. There is an <code>isBanned</code> API to determine whether a User has been banned, but it is asynchronous. You can use flatMap:

<pre>
scala> import com.twitter.util.{Future,Promise}
import com.twitter.util.{Future, Promise}
scala> import com.twitter.util.{Await, Future,Promise}
import com.twitter.util.{Await, Future, Promise}

scala> class User(n: String) { val name = n }
defined class User
Expand All @@ -125,14 +125,14 @@ pru: com.twitter.util.Promise[User] = Promise@897588993(...)
scala> val futBan = pru flatMap isBanned // apply isBanned to future
futBan: com.twitter.util.Future[Boolean] = Promise@1733189548(...)

scala> futBan.get()
scala> Await.result(futBan)
...REPL hangs, futBan not resolved yet...
Ctrl-C
Execution interrupted by signal.

scala> pru.setValue(new User("prudence"))

scala> futBan.get()
scala> Await.result(futBan)
res45: Boolean = false

scala>
Expand Down Expand Up @@ -164,14 +164,14 @@ praw: com.twitter.util.Promise[RawCredentials] = Promise@1341283926(...)
scala> val fcred = praw map normalize // apply normalize to future
fcred: com.twitter.util.Future[Credentials] = Promise@1309582018(...)

scala> fcred.get()
scala> Await.result(fcred)
...REPL hangs, fcred doesn't have a value yet...
Ctrl-C
Execution interrupted by signal.

scala> praw.setValue(new RawCredentials("Florence", "nightingale"))

scala> fcred.get().username
scala> Await.result(fcred).username
res48: String = florence

scala>
Expand Down Expand Up @@ -229,7 +229,7 @@ f23: com.twitter.util.Future[Seq[Int]] = Promise@635209178(...)
scala> val f5 = f23 map (_.sum)
f5: com.twitter.util.Future[Int] = Promise@1954478838(...)

scala> f5.get()
scala> Await.result(f5)
res9: Int = 5

</pre>
Expand All @@ -240,7 +240,7 @@ res9: Int = 5
scala> val ready = Future.join(Seq(f2, f3))
ready: com.twitter.util.Future[Unit] = Promise@699347471(...)

scala> ready.get() // doesn't ret value, but I know my futures are done
scala> Await.result(ready) // doesn't ret value, but I know my futures are done

scala>
</pre>
Expand All @@ -254,21 +254,21 @@ pr7: com.twitter.util.Promise[Int] = Promise@1608532943(...)
scala> val sel = Future.select(Seq(f2, pr7)) // select from 2 futs, one resolved
sel: com.twitter.util.Future[...] = Promise@1003382737(...)

scala> val(complete, stragglers) = sel.get()
scala> val(complete, stragglers) = Await.result(sel)
complete: com.twitter.util.Try[Int] = Return(2)
stragglers: Seq[...] = List(...)

scala> complete.get()
scala> Await.result(complete)
res110: Int = 2

scala> stragglers(0).get() // our list of not-yet-finished futures has one item
...get() hangs the REPL because this straggling future is not finished...
scala> Await.result(stragglers(0)) // our list of not-yet-finished futures has one item
...Await.result() hangs the REPL because this straggling future is not finished...
Ctrl-C
Execution interrupted by signal.

scala> pr7.setValue(7)

scala> stragglers(0).get()
scala> Await.result(stragglers(0))
res113: Int = 7

scala>
Expand Down
12 changes: 6 additions & 6 deletions web/ko/concurrency.textile
Expand Up @@ -36,7 +36,7 @@ h2(#Thread). Thread

스칼라 동시성은 자바 동시성 모델 위에 구현되어 있다.

Sun의 JVM에서 IO-작업 부하가 큰 경우 한 기계 위에 수만개의 쓰레드를 실행할 수 있다.
Sun의 JVM에서 IO-작업 부하가 큰 경우 한 기계 위에 수만개의 쓰레드를 실행할 수 있다.

Thread는 Runnable을 받는다. Thread가 Runnable을 실행하게 만들려면 Thread의 @start@ 를 호출해야 한다.

Expand Down Expand Up @@ -92,7 +92,7 @@ class Handler(socket: Socket) extends Runnable {

이 프로그램의 가장 큰 문제점은 한번에 한 요청밖에 처리하지 못한다는 점이다!

각각의 요청을 쓰레드에 넣었다면 더 좋았을 것이다. 단지 아래 부분을
각각의 요청을 쓰레드에 넣었다면 더 좋았을 것이다. 단지 아래 부분을

<pre>
(new Handler(socket)).run()
Expand Down Expand Up @@ -167,7 +167,7 @@ pool-1-thread-2

h2(#Future). Future

@Future@ 는 비동기적 연산을 나타낸다. 필요한 계산을 Future로 감싼 다음 결과가 필요할 때 그 Future의 @get()@ 메소드를 호출하면 된다. 이 @get()@ 메소드는 블록킹 메소드이다.
@Future@ 는 비동기적 연산을 나타낸다. 필요한 계산을 Future로 감싼 다음 결과가 필요할 때 그 Future의 @get()@ 메소드를 호출하면 된다. 이 @get()@ 메소드는 블록킹 메소드이다.
@Executor@ 는 @Future@ 를 반환한다. Finagle RPC 시스템을 사용한다면 @Future@ 인스턴스에 결과를 담는다. 결과는 경우에 따라 아직 도착하지 않았을 수도 있다.

@FutureTask@ 는 Runnable이며 @Executor@ 가 실행하도록 설계되었다.
Expand All @@ -183,7 +183,7 @@ executor.execute(future)
이제 결과가 필요해졌다. 결과가 나올때까지 블록시키도록 하자.

<pre>
val blockingResult = future.get()
val blockingResult = Await.result(future)
</pre>

*See Also* <a href="finagle.html">스칼라 학교의 Finagle 페이지</a>에는 <code>Future</code>를 사용한 예제가 많이 있다. 그 중에는 Future를 서로 엮는 멋진 방법을 보여주는 것들도 있다. 효율적 스칼라에서도 <a href="http://twitter.github.com/effectivescala/#Twitter's standard libraries-Futures">Future</a>에 대해 다룬다.
Expand Down Expand Up @@ -296,7 +296,7 @@ h2(#example). 안전하지 않은 검색 엔진을 만들자

여기 쓰레드 안전성이 없는 역 인덱스가 있다. 이 역 인덱스는 이름의 일부에 대해 사용자를 연결해준다.

오직 한 쓰레드만 억세스할 수 있다는 순진한 가정하에 작성되어 있다.
오직 한 쓰레드만 억세스할 수 있다는 순진한 가정하에 작성되어 있다.

@mutable.HashMap@ 를 사용하게 되어 있는 추가 기본 생성자 @this()@ 에 유의하라.

Expand Down Expand Up @@ -421,7 +421,7 @@ class FileRecordProducer(path: String) extends UserMaker {

h3. 해결책: 생산자/소비자

비동기적 계산에서 공통된 패턴은 생산자와 소비자를 분리해 둘 사이에는 @Queue@ 를 사용한 통신만 허용하는 것이다. 앞의 검색엔진 인덱스 프로그램에 이를 어떻게 적용할 수 있나 살펴보자.
비동기적 계산에서 공통된 패턴은 생산자와 소비자를 분리해 둘 사이에는 @Queue@ 를 사용한 통신만 허용하는 것이다. 앞의 검색엔진 인덱스 프로그램에 이를 어떻게 적용할 수 있나 살펴보자.

<pre>
import java.util.concurrent.{BlockingQueue, LinkedBlockingQueue}
Expand Down

0 comments on commit de0b553

Please sign in to comment.