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 ( :fredneste 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.deliverenviar os resultados para esse objeto de promessa.derefcumprir sua promessa antes de terminar o cálculo será bloqueado até que você termine. Depois de terminar e delivercumprir 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, derefsignifica 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.
futurechamada 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 deliverexplicitamente, 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 promisechamada) para produzir ( deliver) e consumir ( deref) o resultado da computação . Esses são dois recursos muito distintos e devem ser tratados como tal.
promiseseria 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á delivero resultado.
Em Clojure, promise, future, e delaysã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:
futureirá iniciar o cálculo em um thread de trabalho diferente. derefirá bloquear até que o resultado esteja pronto.
delayexecutará o cálculo preguiçosamente, quando o primeiro cliente usar deref, ou force.
promiseoferece mais flexibilidade, pois seu resultado é fornecido de qualquer forma personalizada usando deliver. Você o usa quando nenhum futureou delaycorresponde ao seu caso de uso.
Em primeiro lugar, a Promiseé a Future. Acho que você quer saber a diferença entre a Promisee a FutureTask.
A Futurerepresenta um valor que não é conhecido atualmente, mas será conhecido no futuro.
A FutureTaskrepresenta 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 Promiserepresenta um resultado que será entregue pelo prometente ao prometido no futuro. Nesse caso, você é o prometido e o prometedor é aquele que lhe deu o Promiseobjeto. Semelhante ao FutureTask, se você tentar acessar o resultado antes de Promiseter sido cumprido, ele será bloqueado até que o prometente cumpra o Promise. Assim que o Promisefor 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 Promisevocê fez para si mesmo.