Tanto os futuros quanto as promessas se bloqueiam até que tenham calculado seus valores, então qual é a diferença entre eles?
Tanto os futuros quanto as promessas se bloqueiam até que tenham calculado seus valores, então qual é a diferença entre eles?
Respostas:
Respondendo em termos de Clojure, aqui estão alguns exemplos do screencast de Sean Devlin :
(def a-promise (promise))
(deliver a-promise :fred)
(def f (future (some-sexp)))
(deref f)
Observe que, na promessa, você está entregando explicitamente um valor que selecionou em um cálculo posterior ( :fred
neste caso). O futuro, por outro lado, está sendo consumido no mesmo lugar em que foi criado. O some-expr
é presumivelmente lançado nos bastidores e calculado em conjunto (eventualmente), mas se permanecer sem avaliação no momento em que for acessado, o thread bloqueia até que esteja disponível.
editado para adicionar
Para ajudar a distinguir ainda mais entre uma promessa e um futuro, observe o seguinte:
promise
. Esse objeto de promessa agora pode ser passado para qualquer thread.deliver
enviar os resultados para esse objeto de promessa.deref
cumprir sua promessa antes de terminar o cálculo será bloqueado até que você termine. Depois de terminar e deliver
cumprir a promessa, a promessa não bloqueará mais.deref
é o futuro. Se o cálculo já foi concluído, você obtém os resultados dele. Se ainda não foi concluído, você bloqueia até que seja concluído. (Provavelmente, se ainda não começou, deref
significa que começou a ser executado, mas isso também não é garantido.)Embora você possa tornar a expressão no futuro tão complicada quanto o código que segue a criação de uma promessa, é duvidoso que isso seja desejável. Isso significa que os futuros são realmente mais adequados para cálculos rápidos e em segundo plano, enquanto as promessas são realmente mais adequadas para caminhos de execução grandes e complicados. Também, as promessas parecem, em termos de cálculos disponíveis, um pouco mais flexíveis e orientadas para o criador da promessa fazendo o trabalho e outro fio colhendo a colheita. Os futuros são mais orientados para iniciar automaticamente um thread (sem a sobrecarga feia e propensa a erros) e continuar com outras coisas até que você - o thread de origem - precise dos resultados.
future
chamada pode incluir N sexprs.
Futuro e Promessa são mecanismos para comunicar o resultado da computação assíncrona do produtor para o (s) consumidor (es).
No caso de Future, o cálculo é definido no momento da criação do Future e a execução assíncrona começa "ASAP". Ele também "sabe" como gerar uma computação assíncrona.
No caso do Promise, o cálculo , sua hora de início e [possível] chamada assíncrona são desacoplados do mecanismo de entrega. Quando o resultado do cálculo está disponível, o Produtor deve chamar deliver
explicitamente, o que também significa que o Produtor controla quando o resultado fica disponível.
For Promises Clojure comete um erro de design ao usar o mesmo objeto (resultado da promise
chamada) para produzir ( deliver
) e consumir ( deref
) o resultado da computação . Esses são dois recursos muito distintos e devem ser tratados como tal.
promise
seria conveniente. Consumidores 'maus' são raros; nada o impede de construir sua própria abstração em cima de promessas.
(defn undeliverable-promise [] (let [p (promise)] (reify clojure.lang.IDeref (deref [_] (deref p)) clojure.lang.IBlockingDeref (deref [_ ms val] (deref p ms val)) clojure.lang.IPending (isRealized [_] (.isRealized p)) clojure.lang.IFn (invoke [_ _] nil))))
Já existem respostas excelentes, então apenas adicionando o resumo "como usar":
Ambos
Criar promessa ou futuro retorna uma referência imediatamente. Esta referência bloqueia em @ / deref até que o resultado do cálculo seja fornecido por outro thread.
Futuro
Ao criar o futuro, você fornece um trabalho síncrono a ser feito. É executado em um thread do pool ilimitado dedicado.
Promessa
Você não dá argumentos ao criar promessa. A referência deve ser passada para outro encadeamento de 'usuário' que será deliver
o resultado.
Em Clojure, promise
, future
, e delay
são promessa semelhante objetos. Todos eles representam uma computação que os clientes podem esperar usando deref
(ou @
). Os clientes reutilizam o resultado, para que o cálculo não seja executado várias vezes.
Eles diferem na forma como o cálculo é realizado:
future
irá iniciar o cálculo em um thread de trabalho diferente. deref
irá bloquear até que o resultado esteja pronto.
delay
executará o cálculo preguiçosamente, quando o primeiro cliente usar deref
, ou force
.
promise
oferece mais flexibilidade, pois seu resultado é fornecido de qualquer forma personalizada usando deliver
. Você o usa quando nenhum future
ou delay
corresponde ao seu caso de uso.
Em primeiro lugar, a Promise
é a Future
. Acho que você quer saber a diferença entre a Promise
e a FutureTask
.
A Future
representa um valor que não é conhecido atualmente, mas será conhecido no futuro.
A FutureTask
representa o resultado de um cálculo que acontecerá no futuro (talvez em algum pool de threads). Quando você tenta acessar o resultado, se o cálculo ainda não aconteceu, ele bloqueia. Caso contrário, o resultado é retornado imediatamente. Não há nenhuma outra parte envolvida no cálculo do resultado, pois o cálculo é especificado por você antecipadamente.
A Promise
representa um resultado que será entregue pelo prometente ao prometido no futuro. Nesse caso, você é o prometido e o prometedor é aquele que lhe deu o Promise
objeto. Semelhante ao FutureTask
, se você tentar acessar o resultado antes de Promise
ter sido cumprido, ele será bloqueado até que o prometente cumpra o Promise
. Assim que o Promise
for cumprido, você obterá o mesmo valor sempre e imediatamente. Ao contrário de um FutureTask
, há uma outra parte envolvida aqui, aquela que fez o Promise
. Essa outra parte é responsável por fazer o cálculo e cumprir o Promise
.
Nesse sentido, a FutureTask
é um que Promise
você fez para si mesmo.