Diferença entre wait () e sleep ()


1204

Qual é a diferença entre a wait()e sleep()em Threads?

Estou entendendo que um wait()segmento -ing ainda está no modo de execução e usa ciclos de CPU, mas um sleep()-ing não consome nenhum ciclo de CPU correto?

Por que temos os dois wait() e sleep(): como a implementação deles varia em um nível inferior?


50
pergunta muito boa. a semântica de ambos é fácil de confundir.
Andreas Petersson

1
Perguntas muito boas, mas são 2 em um. Por que temos os dois não é o mesmo que eles podem (e não são!) Implementados em um nível inferior. Eu já respondi a isso também.
Estani

Suponha que um encadeamento A esteja em um bloco sincronizado e, enquanto estiver no processador, esse encadeamento é recebido e entregue a outro encadeamento B. agora em qual estado o encadeamento A irá, os outros encadeamentos que esperam nesse bloco sincronizado entrarão agora ?
Peter Peter

1
Aqui está um bom artigo descrevendo-o: qat.com/using-waitnotify-instead-thread-sleep-java
Triton Man

3
sua excatly o oposto - o sono "usos" todos os seus CPU ciclos disponíveis, mas uma vez que o segmento vai estar em "espera" -Estado estes podem ser cedidos, se necessário - na verdade a maioria sistemas operacionais produzir automaticamente os ciclos de IF é possível, portanto, seu encadeamento não criará nenhuma carga de CPU real ... mas sim em sistemas operacionais mais antigos. Object.wait (), por outro lado, NUNCA usa nenhum ciclo (enquanto não é notificado) porque isso é realizado através de interrupções de software em muitos casos - bloqueios privados, transitórios e transparentes, implementados pela JVM. Thread.sleep é uma má prática.
specializt

Respostas:


838

Um waitpode ser "acordado" por outro encadeamento que chama notifyo monitor que está sendo aguardado, enquanto um sleepnão pode. Também um wait(e notify) deve ocorrer em um bloco synchronizedno objeto de monitor, ao passo sleepque não:

Object mon = ...;
synchronized (mon) {
    mon.wait();
} 

Nesse ponto, o encadeamento atualmente em execução aguarda e libera o monitor . Outra discussão pode fazer

synchronized (mon) { mon.notify(); }

(no mesmo monobjeto) e o primeiro segmento (assumindo que seja o único segmento aguardando no monitor) será ativado.

Você também pode ligar notifyAllse mais de um segmento estiver aguardando no monitor - isso ativará todos eles . No entanto, apenas um dos encadeamentos poderá agarrar o monitor (lembre-se de que ele waitestá em um synchronizedbloco) e continuar - os outros serão bloqueados até que possam adquirir o bloqueio do monitor.

Outro ponto é que você chama waitem Objectsi (ou seja, você espera no monitor de um objeto), enquanto você chama sleepde Thread.

No entanto, outro ponto é que você pode obter wakeups espúrias de wait(ou seja, a discussão que está esperando currículos sem razão aparente). Você deve sempre waitgirar em algumas condições, como a seguir:

synchronized {
    while (!condition) { mon.wait(); }
}

131
Não, eu não posso. Só pode ser interrompido.
Peter Štibraný

9
Ao interromper, você deve saber qual thread deseja interromper. Quando você está chamando notificar, você só precisa de um objeto e não se importa se há outro encadeamento que 'aguarde' nesse objeto. esperar / notificar é usado para comunicação, enquanto o sono é usado para, ehm, dormir.
Peter Štibraný

28
@ Geek - por que no mundo você diz wait () desperdiça ciclos de CPU?
Robert Munteanu

25
A interrupção é planejada como um mecanismo para encorajar suavemente um encadeamento a parar completamente de executar e cancelar as operações restantes. wait/ notifygeralmente são usados ​​para aguardar que outro segmento realize uma tarefa ou para esperar até que uma determinada condição seja satisfeita.
Louis Wasserman

13
Eu li todas as respostas, mas ainda sinto falta de informações. Muitas pessoas escreveram as definições do Javadoc e também o significado das duas palavras em inglês, mas eu não vejo Por que eu deveria usar o sono em vez de esperar? Qual é a diferença de benchmarking e velocidade entre os dois? Se eu posso fazer tudo o que posso fazer com o sono, por que devo escolher dormir?
precisa

334

Uma diferença importante ainda não mencionada é que, durante o sono, um Thread não libera os bloqueios que ele mantém, enquanto espera libera o bloqueio no objeto que wait()é chamado.

synchronized(LOCK) {
    Thread.sleep(1000); // LOCK is held
}


synchronized(LOCK) {
    LOCK.wait(); // LOCK is not held
}

105
A espera apenas libera o bloqueio para o objeto que você chama de wait (). Não libera outros bloqueios.
Jon Skeet

16
Na verdade, você não precisa ligar para dormir de dentro de um cadeado - os cadeados e a espera / notificação andam de mãos dadas, mas os cadeados e o sono não têm relação.
21420 oxbow_lakes

7
@oxbow_lakes - eu diria que você não deve dormir com bloqueios, existem poucos casos de uso para isso. Só queria apontar as diferenças.
Robert Munteanu

5
@RobertMunteanu, Sua resposta afirma enganosamente que sleepcontém bloqueios java , mas não. Para ter uma comparação justa, compararíamos synchronized(OUTER_LOCK){ Thread.sleep(1000); }com synchronized(OUTER_LOCK){ synchronized(LOCK){LOCK.wait();} }e podemos ver que ambas as instruções não liberam o OUTER_LOCK. Se houver alguma diferença, podemos dizer que sleepnão usa explicitamente bloqueios java , mas a pergunta é sobre a citação "como sua implementação varia em um nível inferior?" entre aspas.
Pacerier 11/08/14

2
O @Pacerier wait()está associado à condição do bloqueio mais interno do qual é chamado, no seu exemplo de código, wait()só pode ser liberado LOCKe não OUTER_LOCK. É assim que o monitor Java é projetado de qualquer maneira. Uma comparação justa seria synchronized(OUTER_LOCK){ synchronized(LOCK) { Thread.sleep(1000); } }e synchronized(OUTER_LOCK){ synchronized(LOCK) { LOCK.wait(); } }. Neste caso sleep()vai realizar ambas as fechaduras enquanto wait()lançará LOCKmas ainda mantêmOUTER_LOCK
danze

244

Achei este post útil. Ela coloca a diferença entre Thread.sleep(), Thread.yield()e Object.wait()em termos humanos. Citar:

Eventualmente, tudo se resume ao agendador do sistema operacional, que distribui horários para processos e threads.

sleep(n)diz: "Eu terminei com o meu horário e, por favor, não me dê outro por pelo menos n milissegundos". O sistema operacional nem tenta agendar o encadeamento em suspensão até que o tempo solicitado tenha passado.

yield()diz: "Já terminei o meu horário, mas ainda tenho trabalho a fazer." O sistema operacional está livre para fornecer imediatamente ao thread outro intervalo de tempo, ou para fornecer outro thread ou processar a CPU que o thread de saída acabou de abrir.

wait()diz: “Eu terminei com o meu horário. Não me dê outro horário até que alguém ligue para notificar (). ” Assim como sleep()no sistema operacional, o sistema operacional nem tentará agendar sua tarefa, a menos que alguém ligue notify()(ou um de alguns outros cenários de ativação).

Os encadeamentos também perdem o restante de sua divisão do tempo quando executam E / S de bloqueio e em algumas outras circunstâncias. Se um encadeamento funciona com toda a divisão do tempo, o SO assume o controle à força, como se yield()tivesse sido chamado, para que outros processos possam ser executados.

Você raramente precisa yield(), mas se você tiver um aplicativo de computação pesada com limites lógicos de tarefas, inserir um yield() pode melhorar a capacidade de resposta do sistema (às custas do tempo - as alternâncias de contexto, mesmo apenas para o SO e vice-versa, não são gratuitas). Avalie e teste contra as metas de que gosta, como sempre.


Rendimento é basicamente dependente de plataforma ... javamex.com/tutorials/threads/yield.shtml
Pacerier

a explicação de sleep(n)está dizendo implicitamente que o segmento em execução no momento renuncia voluntariamente ao monitor do bloqueio, o que não é verdade . Citação do javadoc do Thread : "O thread não perde a propriedade de nenhum monitor".
Clint Eastwood

2
@ Jonathan, não há menção de monitores na resposta, e isso ocorre porque sleepnão há nenhum comportamento especial em relação ao monitor do que qualquer outra chamada de método Java, ou seja, ele não os interage ou modifica de forma alguma. Se você disser algo sobre monitores, deverá especificar que wait, além do que foi dito acima, renunciará temporariamente ao bloqueio no objeto em que é chamado.
Pqnet 03/07/2015

Como a notificação funciona no nível do agendador do SO? Notificar chama algum tipo de manipulador de eventos com um ID de thread específico, permitindo que o planejador coloque o thread relevante de volta na fila em execução? Também tenho outra pergunta: onde o conceito de spinlock se encaixa? Seria relevante apenas para o sono ou a própria espera usa o spinlock em um nível muito baixo?
precisa saber é o seguinte

@Erich, use wait(n)para comparar sleep(n). Não faz sentido comparar usando o no-arg.
Pacerier

68

Há muitas respostas aqui, mas não consegui encontrar a distinção semântica mencionada em nenhuma.

Não é sobre o próprio tópico; ambos os métodos são necessários, pois suportam casos de uso muito diferentes.

sleep()envia o Thread para suspensão como antes, apenas compacta o contexto e para de executar por um tempo predefinido. Portanto, para ativá-lo antes do tempo devido, você precisa conhecer a referência do Thread. Essa não é uma situação comum em um ambiente multithread. É usado principalmente para sincronização de tempo (por exemplo, ativação em exatamente 3,5 segundos) e / ou imparcialidade codificada (apenas durma um pouco e deixe outros threads funcionarem).

wait(), pelo contrário, é um mecanismo de sincronização de encadeamento (ou mensagem) que permite notificar um encadeamento do qual você não tem referência armazenada (nem cuidado). Você pode pensar nisso como um padrão de publicação-assinatura ( wait== inscrever-se e notify()== publicar). Basicamente, usando o notify () você está enviando uma mensagem (que pode até não ser recebida e normalmente você não se importa).

Para resumir, você normalmente usa sleep()para sincronização de tempo e sincronização multithread wait().

Eles poderiam ser implementados da mesma maneira no sistema operacional subjacente ou não (como as versões anteriores do Java não tinham multithreading real; provavelmente algumas VMs pequenas também não fazem isso). Não esqueça que o Java é executado em uma VM; portanto, seu código será transformado em algo diferente de acordo com a VM / OS / HW em que ele é executado.


54

Aqui, listei algumas diferenças importantes entre wait()e sleep()métodos.
PS: Clique também nos links para ver o código da biblioteca (trabalho interno, basta brincar um pouco para entender melhor).

esperar()

  1. wait() O método libera o bloqueio.
  2. wait()é o método da Objectclasse
  3. wait() é o método não estático - public final void wait() throws InterruptedException { //...}
  4. wait()deve ser notificado por notify()ou notifyAll()métodos.
  5. wait() O método precisa ser chamado de um loop para lidar com o alarme falso.

  6. wait() O método deve ser chamado a partir do contexto sincronizado (ou seja, método ou bloco sincronizado), caso contrário, ele lançará IllegalMonitorStateException

dormir()

  1. sleep() O método não libera o bloqueio.
  2. sleep()é o método da java.lang.Threadclasse
  3. sleep() é o método estático - public static void sleep(long millis, int nanos) throws InterruptedException { //... }
  4. após o período especificado, sleep()é concluído.
  5. sleep()melhor não ligar do loop (ou seja, veja o código abaixo ).
  6. sleep()pode ser chamado de qualquer lugar. não há requisito específico.

Ref: Diferença entre Esperar e Dormir

Snippet de código para chamar o método de espera e suspensão

synchronized(monitor){
    while(condition == true){ 
        monitor.wait()  //releases monitor lock
    }

    Thread.sleep(100); //puts current thread on Sleep    
}

transição de encadeamento para diferentes estados de encadeamento


É correto que um segmento inativo possa ser ativado por chamadas para notify ()? Algumas das outras postagens aqui parecem sugerir que um segmento adormecido não pode ser acordado, mas interrompido.
berimbolo

Sim, Thread.sleep()é usado para disponibilizar o tempo do processador para os outros threads. o período de sono pode ser encerrado por interrupções (ou seja, pela JVM). Leia este stackoverflow.com/questions/4264355/…
roottraveller

Esse post também diz que interrupt () é o que ativa um thread adormecido? Eu estava me referindo ao diagrama de estado do encadeamento que você postou onde diz notificar ou notificar. Todos trazem um encadeamento adormecido (sem espera) de volta para pronto para execução. Eu só quero ter certeza de que entendo isso.
22717 berimbolo

@berimbolo notify()ou notifyAll()são Objectmétodos de classe. portanto, eles estarão disponíveis com obj de toda classe (ou seja, aqui também com Threadclasse). consulte o código grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/…
roottraveller

2
OK Preciso ler mais sobre o agendamento de encadeamentos, pois não consigo encontrar exemplos de notificações () ou notifyAll () ativando encadeamentos em suspensão, apenas interrompendo () fazendo isso. Todos os exemplos relacionam notify () e notifyAll () a threads que aguardam em algum objeto de monitor.
berimbolo

29

Existem algumas notas importantes que concluo depois de trabalhar em esperar e dormir, primeiro dê uma olhada na amostra usando wait () e sleep ():

Exemplo1 : usando wait () e sleep ():

synchronized(HandObject) {
    while(isHandFree() == false) {
        /* Hand is still busy on happy coding or something else, please wait */
        HandObject.wait();
    }
}

/* Get lock ^^, It is my turn, take a cup beer now */
while (beerIsAvailable() == false) {
    /* Beer is still coming, not available, Hand still hold glass to get beer,
       don't release hand to perform other task */
    Thread.sleep(5000);
}

/* Enjoy my beer now ^^ */
drinkBeers();

/* I have drink enough, now hand can continue with other task: continue coding */
setHandFreeState(true);
synchronized(HandObject) {
    HandObject.notifyAll();
}

Vamos esclarecer algumas notas principais:

  1. Ligue para :
    • wait (): chame o thread atual que contém o objeto HandObject
    • sleep (): chamar a tarefa de execução de thread get beer (é o método de classe, portanto, afeta o thread em execução atual)
  2. Sincronizado :
    • wait (): quando sincronizado com vários threads, acessa o mesmo objeto (HandObject) (quando precisa de comunicação entre mais de um thread (thread executa codificação, thread executa obtém cerveja) acesso ao mesmo objeto HandObject)
    • sleep (): ao aguardar condição para continuar a execução (aguardando cerveja disponível)
  3. Segure a trava :
    • wait (): libera o bloqueio para outro objeto ter chance de executar (o HandObject é gratuito, você pode executar outro trabalho)
    • sleep (): mantenha a trava por pelo menos t vezes (ou até a interrupção) (meu trabalho ainda não terminou, continuo mantendo a trava e aguardando alguma condição para continuar)
  4. Condição de despertar :
    • wait (): até a chamada notify (), notifyAll () do objeto
    • sleep (): até que pelo menos o tempo expire ou chame a interrupção
  5. E o último ponto é usado quando como estani indicar:

você normalmente usa sleep () para sincronização horária e wait () para sincronização multithread.

Por favor me corrija se eu estiver errado.


26

Diferença entre wait () e sleep ()

  • A diferença fundamental é que wait()é Objecte sleep()é um método estático de Thread.

  • A principal diferença é que wait()libera o bloqueio enquanto sleep()não libera nenhum bloqueio enquanto aguarda.

  • wait()é usado para comunicação entre threads enquanto sleep()é usado para introduzir uma pausa na execução, geralmente.

  • wait()deve ser chamado de dentro de sincronizar ou então temos um IllegalMonitorStateException, enquanto sleep() pode ser chamado em qualquer lugar.

  • Para iniciar um thread novamente wait(), você precisa chamar notify()ou notifyAll(). Quanto sleep(),ao encadeamento, é iniciado após um intervalo de tempo especificado.

Semelhanças

  • Ambos fazem com que o encadeamento atual entre no estado Não Executável .
  • Ambos são métodos nativos .

18

Essa é uma pergunta muito simples, porque esses dois métodos têm um uso totalmente diferente.

A principal diferença é esperar para liberar a trava ou monitor enquanto o sono não libera nenhuma trava ou monitor enquanto aguarda. A espera é usada para comunicação entre encadeamentos enquanto a suspensão é usada para introduzir uma pausa na execução.

Esta foi apenas uma explicação clara e básica, se você quiser mais do que isso, continue lendo.

No caso de o wait()thread do método entrar no estado de espera e ele não voltará automaticamente até chamarmos o notify()método (ou notifyAll()se você tiver mais de um thread no estado de espera e desejar ativar todos esses threads). E você precisa sincronizado ou o bloqueio objeto ou bloqueio classe para acesso a wait()ou notify()ou notifyAll()métodos. E mais uma coisa, o wait()método é usado para comunicação entre segmentos, porque se um segmento entrar no estado de espera, você precisará de outro segmento para ativar esse segmento.

Mas, nesse caso, sleep()é um método usado para manter o processo por alguns segundos ou o tempo que você deseja. Porque você não precisa de provocar qualquer notify()ou notifyAll()método para obter isso de volta fio. Ou você não precisa de nenhum outro segmento para retornar esse segmento. Por exemplo, se você deseja que algo aconteça após alguns segundos, como em um jogo após a vez do usuário, você deseja que o usuário espere até que o computador seja reproduzido. Você pode mencionar o sleep()método

E mais uma diferença importante que é frequentemente solicitada nas entrevistas: sleep()pertence à Threadclasse e wait()pertence à Objectclasse.

Essas são todas as diferenças entre sleep()e wait().

E há uma semelhança entre os dois métodos: ambos são instruções verificadas, então você precisa tentar pegar ou lançar para acessar esses métodos.

Eu espero que isso te ajude.


16

fonte: http://www.jguru.com/faq/view.jsp?EID=47127

Thread.sleep()envia o thread atual para o estado "Não executável" por algum tempo. O encadeamento mantém os monitores adquiridos - ou seja, se o encadeamento está atualmente em um bloco ou método sincronizado, nenhum outro encadeamento pode entrar nesse bloco ou método. Se outro segmento ligar, t.interrupt()ele ativará o fio inativo.

Observe que sleep é um método estático, o que significa que sempre afeta o encadeamento atual (aquele que está executando o método sleep). Um erro comum é chamar t.sleep()onde t é um segmento diferente; mesmo assim, é o encadeamento atual que dorme, não o encadeamento t.

t.suspend()está obsoleto. É possível interromper um thread diferente do atual. Um encadeamento suspenso mantém todos os seus monitores e, como esse estado não é interrompível, é propenso a conflitos.

object.wait()envia o encadeamento atual para o estado "Não executável" , como sleep(), mas com um toque. A espera é chamada em um objeto, não em um encadeamento; chamamos esse objeto de "objeto de bloqueio". Antes de lock.wait()ser chamado, o encadeamento atual deve ser sincronizado no objeto de bloqueio; wait() libera esse bloqueio e adiciona o thread à "lista de espera" associada ao bloqueio. Mais tarde, outro encadeamento pode ser sincronizado no mesmo objeto e chamada de bloqueio lock.notify(). Isso ativa o thread original em espera. Basicamente, wait()/ notify()é como sleep()/ interrupt(), apenas o encadeamento ativo não precisa de um ponteiro direto para o encadeamento adormecido, mas apenas para o objeto de bloqueio compartilhado.


14

Esperar e dormir são duas coisas diferentes:

  • No sleep()segmento, pára de funcionar pela duração especificada.
  • No wait()thread, ele pára de funcionar até que o objeto que está sendo aguardado seja notificado, geralmente por outros threads.

mas você pode interromper um thread adormecido. Nesse caso espera () é de facto redundantes desperdiça ciclos de CPU também :-(
Geek

9
A espera não desperdiça ciclos de CPU.
Peter Štibraný

1
@ Peter - eu acho que sim. Ele espera () por sua parte dos ciclos da CPU e, em seguida, o SO fornece os ciclos da CPU para outros Threads. Eu acho que isso pode depender do sistema operacional, não tenho certeza.
24410 Geek

3
Seria uma implementação muito ruim de wait () se desperdiçasse ciclos de CPU. A opção esperar / notificar é bastante utilizada na comunicação entre segmentos.
Peter Štibraný

2
@Pacerier, as duas construções destinam-se a uma finalidade diferente. Se você deseja que um encadeamento pare por um período fixo de tempo sleep, use-o , se desejar que ele pare até que alguma entrada venha da outra que você usa wait/ notify. interruptdestina-se a uma maneira de sinalizar um thread que ele deve parar de fazer o que está fazendo e terminar. É tratado por sleep, waitmas também bloqueando funções de E / S (e você pode implementar funções com o mesmo comportamento chamando o método Thread.interrupted()). Quanto ao desempenho, as funções geralmente são otimizadas para o objetivo em que foram projetadas.
Pqnet 03/07/2015

11

sleepé um método de Thread, waité um método de Object, assim wait/notifycomo uma técnica de sincronização de dados compartilhados em Java (usando o monitor ), mas sleepé um método simples de encadeamento para pausar a si próprio.


8

sleep () é um método usado para reter o processo por alguns segundos ou o tempo desejado, mas em caso de wait () o encadeamento do método fica em estado de espera e não volta automaticamente até que chamemos o notify () ou notifyAll ().

A principal diferença é que wait () libera o bloqueio ou monitor enquanto o modo sleep () não libera nenhum bloqueio ou monitor enquanto aguarda. A espera é usada para comunicação entre encadeamentos, enquanto a suspensão é usada para introduzir uma pausa na execução, geralmente.

Thread.sleep () envia o thread atual para o estado “Não pode ser executado” por algum tempo. O thread mantém os monitores que adquiriu - ou seja, se o thread estiver atualmente em um bloco ou método sincronizado, nenhum outro thread poderá entrar nesse bloco ou método. Se outro thread chamar t.interrupt (), ele ativará o thread inativo. Observe que sleep é um método estático, o que significa que sempre afeta o encadeamento atual (aquele que está executando o método sleep). Um erro comum é chamar t.sleep () onde t é um encadeamento diferente; mesmo assim, é o encadeamento atual que dorme, não o encadeamento t.

object.wait () envia o encadeamento atual para o estado “Não executável”, como sleep (), mas com um toque. A espera é chamada em um objeto, não em um encadeamento; chamamos esse objeto de "objeto de bloqueio". Antes de lock.wait () ser chamado, o encadeamento atual deve ser sincronizado no objeto lock; wait () libera esse bloqueio e adiciona o thread à "lista de espera" associada ao bloqueio. Posteriormente, outro encadeamento pode ser sincronizado no mesmo objeto de bloqueio e chamar lock.notify (). Isso ativa o thread original em espera. Basicamente, wait () / notify () é semelhante a sleep () / interrupt (), apenas o encadeamento ativo não precisa de um ponteiro direto para o encadeamento adormecido, mas apenas para o objeto de bloqueio compartilhado.

synchronized(LOCK) {   
   Thread.sleep(1000); // LOCK is held
}

synchronized(LOCK) {   
   LOCK.wait(); // LOCK is not held
}

Vamos categorizar todos os pontos acima:

Call on:

  • wait (): chama um objeto; o encadeamento atual deve ser sincronizado no objeto de bloqueio.
  • sleep (): invoca um thread; sempre em execução no thread.

Synchronized:

  • wait (): quando vários threads sincronizados acessam o mesmo objeto, um por um.
  • sleep (): quando vários encadeamentos sincronizados, aguardam a suspensão do encadeamento adormecido.

Hold lock:

  • wait (): libere o bloqueio para que outros objetos tenham chance de executar.
  • sleep (): mantenha o bloqueio por pelo menos t vezes se o tempo limite especificado ou alguém interromper.

Wake-up condition:

  • wait (): até a chamada notify (), notifyAll () do objeto
  • sleep (): até que pelo menos o tempo expire ou chame interrupção ().

Usage:

  • sleep (): para sincronização de tempo e;
  • wait (): para sincronização multithread.

Ref: diff sleepewait


6

Em palavras simples, wait is wait Até que outro thread o chame, enquanto sleep é "não execute a próxima instrução" por um período especificado.

Além disso, sleep é um método estático na classe Thread e opera em thread, enquanto wait () está na classe Object e é chamado em um objeto.

Outro ponto, quando você chama wait em algum objeto, o thread envolvido sincroniza o objeto e aguarda. :)


1
Por que você precisa dos dois? Por que dormir () não é suficiente?
24710 Geek

2
Notify é usado para comunicação entre threads. Para chamar a espera, você precisa de algum objeto, sincronize-o e, em seguida, chame a espera. Para ser notificado, você precisa de outro encadeamento para sincronizar no mesmo objeto e ligue para notificar.
Peter Štibraný

6

waite sleepmétodos são muito diferentes:

  • sleep não tem como "acordar",
  • considerando que waittem uma maneira de "acordar" durante o período de espera, por outro thread chamando notifyou notifyAll.

Venha para pensar sobre isso, os nomes são confusos a esse respeito; no entanto, sleepé um nome padrão e waité como o WaitForSingleObjectou WaitForMultipleObjectsna API do Win.


3
Mas podemos interromper um sono, não é? então qual é a diferença com esse sono / interrupção vs espera / notificação?
Pacerier

2
Você pode interromper uma pessoa adormecida, mas só pode notificá-la. Threads são os mesmos.
Rishi

5

Deste post: http://javaconceptoftheday.com/difference-between-wait-and-sleep-methods-in-java/

Método wait ().

1) O thread que chama o método wait () libera o bloqueio que ele mantém.

2) O encadeamento recupera o bloqueio depois que outros encadeamentos chamam os métodos notify () ou notifyAll () no mesmo bloqueio.

3) O método wait () deve ser chamado dentro do bloco sincronizado.

4) O método wait () é sempre chamado em objetos.

5) Os threads em espera podem ser ativados por outros threads chamando os métodos notify () ou notifyAll ().

6) Para chamar o método wait (), o encadeamento deve ter um bloqueio de objeto.

Método sleep ()

1) O thread que chama o método sleep () não libera o bloqueio que ele mantém.

2) o método sleep () pode ser chamado dentro ou fora do bloco sincronizado.

3) o método sleep () é sempre chamado em threads.

4) Os threads adormecidos não podem ser despertados por outros threads. Se feito, o thread lançará InterruptedException.

5) Para chamar o método sleep (), o thread não precisa ter um bloqueio de objeto.


4

Aqui, wait () estará no estado de espera até ser notificado por outro Thread, mas onde o sleep () estará demorando algum tempo .. depois que ele será transferido automaticamente para o estado Ready ...


4
  1. wait()é um método de Objectclasse.
    sleep()é um método de Threadclasse.

  2. sleep()permite que o encadeamento vá para o sleepestado por x milissegundos.
    Quando um thread entra no estado de suspensão it doesn’t release the lock.

  3. wait()permite que a linha solte a trava e goes to suspended state.
    Esse encadeamento estará ativo quando um método notify()ou notifAll()for chamado para o mesmo objeto.


4

Uma grande diferença potencial entre suspensão / interrupção e espera / notificação é que

Gerar uma exceção quando não é necessário é ineficiente. Se você tiver threads se comunicando a uma taxa alta, isso geraria muitas exceções se você estivesse chamando interrupção o tempo todo, o que é um total desperdício de CPU.


+1, um ponto válido na verdade, embora argumentando sobre os internos de implementações podem ser mais relevantes para a análise de desempenho ...
Pacerier

Em outras palavras, a sobrecarga de criação de exceções pode ser significativamente menor do que a sobrecarga da implementação de um sistema contra o outro.
Pacerier

3

Você está correto - Sleep () faz com que esse thread "entre em suspensão" e a CPU apaga e processa outros threads (também conhecidos como alternância de contexto), onde acredito que Wait mantém a CPU processando o thread atual.

Temos os dois porque, embora possa parecer sensato permitir que outras pessoas usem a CPU enquanto você não a estiver usando, na verdade há uma sobrecarga na alternância de contexto - dependendo de quanto tempo durar, pode ser mais caro nos ciclos da CPU para alternar threads do que simplesmente fazer com que seu thread não faça nada por alguns ms.

Observe também que o sono força uma troca de contexto.

Além disso - em geral, não é possível controlar a alternância de contexto - durante a espera que o sistema operacional possa (e espere por mais tempo) optar por processar outros threads.


4
wait () não mantém a CPU processando o thread atual. É como dormir, pois causa também uma mudança de contexto: javamex.com/tutorials/threads/context_switch.shtml . Eu tenho perguntado por meio ano em todo o stackoverflow e parece que ninguém sabe qual é a diferença entre esperar / notificar vs dormir / interromper.
21712 Pacerier

embora o sono não mantenha a CPU no processamento do encadeamento atual, acho que isso é um pouco pesado para a CPU, porque a CPU precisa acompanhar o momento de quando terminar o sono. Não possui esse gatilho externo como "notificar" em espera. Não?
Vladimir Nabokov

@VladimirNabokov, O gatilho externo é interrupt. A hora de término é nno wait(n). ¶¶ Faz 8 anos e ainda ninguém tem a resposta!
Pacerier

3

Os métodos são usados ​​para coisas diferentes.

Thread.sleep(5000);   // Wait until the time has passed.

Object.wait();        // Wait until some other thread tells me to wake up.

Thread.sleep (n) pode ser interrompido, mas Object.wait () deve ser notificado. É possível especificar o tempo máximo de espera: Object.wait(5000)para que seja possível usar wait, er,sleep mas é preciso se preocupar com bloqueios.

Nenhum dos métodos usa a CPU enquanto dorme / espera.

Os métodos são implementados usando código nativo, usando construções semelhantes, mas não da mesma maneira.

Procure você mesmo: O código fonte dos métodos nativos está disponível? O arquivo /src/share/vm/prims/jvm.cppé o ponto de partida ...


O tempo de thread.sleep também pode ser definido como indefinido. O tempo do Object.wait também pode ser definido como definido. Esta resposta não explica por que precisamos de 2 martelos que fazem a mesma coisa.
Pacerier 10/08/14

Thread.sleep(big_num) deve ser interrompido. Object.wait(small_num) pode ser notificado.
Pacerier

3

Aguarde () e durma () Diferenças?

Thread.sleep () Quando o trabalho é concluído, apenas libera a trava para todos. até que nunca libere a trava para ninguém.

  Sleep() take the key, its never release the key to anyone, when its work completed then only its release then only take the key waiting stage threads.

Object.wait () Quando estiver indo para o estágio de espera, ele liberará a chave e estará aguardando alguns dos segundos com base no parâmetro.

Por exemplo:

você está tomando o café na sua mão direita, você pode pegar outra pessoa da mesma mão; quando você pousa, então pega outro objeto do mesmo tipo aqui. Além disso. isto é sono () você dorme tempo que você não fez nenhum trabalho, você está dormindo apenas .. o mesmo aqui também.

esperar(). quando você é colocado no chão e assume outra, enquanto espera, isso é esperar

você reproduz filme ou qualquer coisa em seu sistema, assim como o reprodutor, não pode reproduzir mais de um de cada vez, é aqui, quando você fecha e escolhe outro filme ou música de alguém enquanto é chamado de espera


3

waitlibera a fechadura e sleepnão. Um segmento em estado de espera é elegível para acordar logo notifyou notifyAllé chamado. No entanto, no caso de sleepo thread manter a trava, ele só será elegível quando o tempo de suspensão terminar.


Portanto, se o thread estiver inativo por 10 segundos e uma exceção interrompida acontecer ????
Geek

@ Geek An InterruptedExceptioné lançado, como diz o Javadoc.
Marquês de Lorne

@EJP: Você é o mesmo EJP que esteve nos fóruns do sun.java.com? Pelo menos a sua pontuação sugere mesmo :-)
Geek

2

sleep()O método faz com que o encadeamento atual passe do estado de execução para o estado do bloco por um tempo especificado. Se o encadeamento atual tiver o bloqueio de qualquer objeto, ele continuará mantendo-o, o que significa que outros encadeamentos não podem executar nenhum método sincronizado nesse objeto de classe.

wait() O método faz com que o encadeamento atual entre no estado do bloco por um tempo especificado ou até ser notificado, mas nesse caso, o encadeamento libera o bloqueio do objeto (o que significa que outros encadeamentos podem executar qualquer método sincronizado do objeto de chamada.


2

Na minha opinião, a principal diferença entre os dois mecanismos é que dormir / interromper é a maneira mais básica de lidar com threads, enquanto esperar / notificar é uma abstração destinada a facilitar a intercomunicação de threads. Isso significa que dormir / interromper pode fazer qualquer coisa, mas que essa tarefa específica é mais difícil de fazer.

Por que esperar / notificar é mais adequado? Aqui estão algumas considerações pessoais:

  1. Força a centralização. Permite coordenar a comunicação entre um grupo de threads com um único objeto compartilhado. Isso simplifica muito o trabalho.

  2. Força a sincronização. Porque faz com que o programador encerre a chamada para aguardar / notificar em um bloco sincronizado.

  3. É independente da origem e número do encadeamento. Com essa abordagem, você pode adicionar mais threads arbitrariamente, sem editar os outros tópicos ou acompanhar os existentes. Se você usou suspensão / interrupção, primeiro você precisa manter as referências aos segmentos em suspensão e depois interrompê-los um a um, manualmente.

Um exemplo da vida real que é bom para explicar isso é um restaurante clássico e o método que o pessoal usa para se comunicar entre eles: os garçons deixam os pedidos do cliente em um local central (uma placa de cortiça, uma mesa etc.), tocam uma campainha e os trabalhadores da cozinha vêm atender a esses pedidos. Quando o curso estiver pronto, o pessoal da cozinha tocará novamente a campainha para que os garçons estejam cientes e os levem aos clientes.


2

Exemplo sobre suspensão não libera bloqueio e espera faz

Aqui existem duas classes:

  1. Principal : Contém o método principal e dois threads.
  2. Singleton : Esta é a classe singleton com dois métodos estáticos getInstance () e getInstance (boolean isWait).

    public class Main {
    
    private static Singleton singletonA = null;
    private static Singleton singletonB = null;
    
    public static void main(String[] args) throws InterruptedException {
    
    Thread threadA = new Thread() {
        @Override
        public void run() {
    
            singletonA = Singleton.getInstance(true);
    
        }
    };
    
    Thread threadB = new Thread() {
        @Override
        public void run() {
            singletonB = Singleton.getInstance();
    
            while (singletonA == null) {
                System.out.println("SingletonA still null");
            }
    
            if (singletonA == singletonB) {
                System.out.println("Both singleton are same");
            } else {
                System.out.println("Both singleton are not same");
            }
    
        }
    };
    
    threadA.start();
    threadB.start();
    
     }
    }

e

public class Singleton {

    private static Singleton _instance;

    public static Singleton getInstance() {

    if (_instance == null) {
        synchronized (Singleton.class) {
            if (_instance == null)
                _instance = new Singleton();
        }
    }
    return _instance;

}

public static Singleton getInstance(boolean isWait) {

    if (_instance == null) {
        synchronized (Singleton.class) {
            if (_instance == null) {
                if (isWait) {
                    try {
                        // Singleton.class.wait(500);//Using wait
                        Thread.sleep(500);// Using Sleep
                        System.out.println("_instance :"
                                + String.valueOf(_instance));
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }

                _instance = new Singleton();
            }
        }
    }
    return _instance;

 }
}

Agora, execute este exemplo, você obterá abaixo da saída:

_instance :null
Both singleton are same

Aqui, as instâncias Singleton criadas por threadA e threadB são iguais. Isso significa que o threadB está esperando do lado de fora até o threadA liberar seu bloqueio.

Agora mude o Singleton.java comentando Thread.sleep (500); método e descomentando Singleton.class.wait (500); . Aqui por causa de Singleton.class.wait (500); O método threadA libera todos os bloqueios adquiridos e passa para o estado "Não executável", o threadB recebe alterações para inserir no bloco sincronizado.

Agora execute novamente:

SingletonA still null
SingletonA still null
SingletonA still null
_instance :com.omt.sleepwait.Singleton@10c042ab
SingletonA still null
SingletonA still null
SingletonA still null
Both singleton are not same

Aqui, as instâncias Singleton criadas por threadA e threadB NÃO são iguais devido ao threadB ter alterado para entrar no bloco sincronizado e, após 500 milissegundos, o threadA iniciou sua última posição e criou mais um objeto Singleton.


2

Deve ser chamado a partir do bloco sincronizado: o wait() método é sempre chamado a partir do bloco sincronizado, ou seja, o wait()método precisa bloquear o monitor do objeto antes do objeto no qual é chamado. Mas o sleep()método pode ser chamado de fora do bloco sincronizado, isto é,sleep() método não precisa de nenhum monitor de objeto.

IllegalMonitorStateException: se o wait()método for chamado sem adquirir o bloqueio do objeto, IllegalMonitorStateExceptionserá lançado no tempo de execução, massleep() método nunca lança essa exceção.

Pertence a qual classe: o wait() método pertence à java.lang.Objectclasse, mas o sleep()método pertence à java.lang.Threadclasse.

Chamado a objeto ou thread: o wait() método é chamado em objetos, mas o sleep()método é chamado em Threads, não objetos.

Estado dowait() encadeamento : quando o método é chamado no objeto, o encadeamento que retinha o monitor do objeto passa do estado de execução para o estado de espera e pode retornar ao estado executável somente quando notify()ou o notifyAll()método é chamado nesse objeto. E posteriormente, o agendador de encadeamentos agenda esse encadeamento para passar do estado executável para o estado de execução. Quando sleep()é chamado no encadeamento, ele passa da execução para o estado em espera e pode retornar ao estado executável quando o tempo de suspensão termina.

Quando chamado do bloco sincronizado: quando o wait()método é chamado thread, sai do objeto lock. Mas o sleep()método quando chamado do bloco sincronizado ou do thread do método não deixa o objeto bloqueado.

Para mais referência


provavelmente um URL de referência melhor do que aquele.
Tirou

2

Na página de documentação da Oracle no método wait () de Object:

public final void wait()
  1. Faz com que o thread atual aguarde até que outro thread invoque o notify()método ou o notifyAll()método para este objeto. Em outras palavras, esse método se comporta exatamente como se simplesmente executasse a chamada wait(0).
  2. O encadeamento atual deve possuir o monitor desse objeto. O encadeamento libera a propriedade desse monitor e aguarda até que outro encadeamento notifique os encadeamentos que aguardam a ativação do monitor desse objeto
  3. interrupções e despertares espúrios são possíveis
  4. Esse método deve ser chamado apenas por um encadeamento que é o proprietário do monitor desse objeto

Este método lança

  1. IllegalMonitorStateException - se o encadeamento atual não for o proprietário do monitor do objeto.

  2. InterruptedException- se algum encadeamento interrompeu o encadeamento atual antes ou enquanto o encadeamento atual aguardava uma notificação. O status interrompido do encadeamento atual é limpo quando essa exceção é lançada.

Na página de documentação da oracle, no método sleep () da Threadclasse:

public static void sleep(long millis)
  1. Faz com que o encadeamento atualmente em execução seja suspenso (interrompa temporariamente a execução) pelo número especificado de milissegundos, sujeito à precisão e exatidão dos cronômetros e planejadores do sistema.
  2. O encadeamento não perde a propriedade de nenhum monitor.

Este método lança:

  1. IllegalArgumentException - se o valor de milis for negativo

  2. InterruptedException- se algum segmento interrompeu o segmento atual. O status interrompido do encadeamento atual é limpo quando essa exceção é lançada.

Outra diferença importante:

wait()é um método não estático (método de instância), diferentemente do método estático sleep()(método de classe).


1

wait()é dado dentro de um método sincronizado ao passo que sleep()é dado dentro de um método não sincronizada porque wait()método libertar o bloqueio sobre o objecto, mas sleep()ou yield()faz libertar a lock().


sleep()pode estar dentro de um synchronizedbloco ou método. A resposta não explica nada.
Marquês de Lorne

1
  • O método wait(1000)faz com que o encadeamento atual durma até um segundo .
    • Um encadeamento poderá dormir menos de 1 segundo se receber a chamada notify()ou donotifyAll() método.
  • A chamada para sleep(1000)faz com que o encadeamento atual entre em repouso por exatamente 1 segundo .
    • O encadeamento adormecido também não retém nenhum recurso de bloqueio . Mas o fio em espera sim.

1
sleep(1000)não garante dormir por exatamente 1 segundo. Pode ser interrompido antes.
Lucio

1
Essas postagens são muito confusas. Todas as outras postagens neste segmento dizem que um segmento adormecido mantém a trava e que uma linha em espera NÃO mantém a trava. Da mesma forma, a postagem com o diagrama implica que as chamadas para notificar () ativam threads em suspensão, mas outras postagens (e diagramas de estado da thread) implicam que somente interrupção () ou o período de tempo limite que faz isso. Acabei de pedir uma cópia da simultaneidade de java na prática, algo que eu deveria ter lido há muito tempo!
berimbolo

1

Na verdade, tudo isso está claramente descrito nos documentos Java (mas percebi isso apenas depois de ler as respostas).

http://docs.oracle.com/javase/8/docs/api/index.html :

wait () - O encadeamento atual deve possuir o monitor desse objeto. O encadeamento libera a propriedade desse monitor e aguarda até que outro encadeamento notifique os encadeamentos que aguardam no monitor desse objeto para ativar por meio de uma chamada ao método de notificação ou pelo método notifyAll. O encadeamento então espera até que possa obter novamente a propriedade do monitor e retoma a execução.

sleep () - Faz com que o encadeamento atualmente em execução seja interrompido (interrompa temporariamente a execução) pelo número especificado de milissegundos, sujeito à precisão e exatidão dos cronômetros e planejadores do sistema. O encadeamento não perde a propriedade de nenhum monitor.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.