Diagrama de status do thread
Os tópicos incluem os 5 estados a seguir.
1. Novo Estado: Depois que o objeto Thread for criado, ele entra no novo estado. Por exemplo, Thread Thread = new Thread ().
2. Estado pronto (executável): também conhecido como "estado executável". Depois que o objeto Thread for criado, outros threads chamam o método START () do objeto para iniciar o thread. Por exemplo, thread.start (). Um tópico em um estado pronto pode estar programado para executar pela CPU a qualquer momento.
3. Estado em execução (em execução): o encadeamento obtém permissões de CPU para execução. Deve -se notar que os threads só podem entrar no estado em execução do estado pronto.
4. Estado bloqueado: Estado bloqueado significa que o thread renuncia aos direitos de uso da CPU por algum motivo e para temporariamente a execução. Não é até o encadeamento entrar no estado pronto que ele tem a chance de ir ao estado de corrida. Existem três tipos de bloqueio:
(01) Esperando para bloquear - chamando o método Wait () Thread's Wait (), deixe o tópico aguarde a conclusão de um determinado trabalho.
(02) Bloqueio sincronizado-Um encadeamento falha ao adquirir trava de sincronização sincronizada (porque a trava é ocupada por outros threads), ele entrará em um estado de bloqueio sincronizado.
(03) Outro bloqueio-o thread entrará em um estado de bloqueio ligando para o sono () ou ingressar () do thread ou emitindo uma solicitação de E/S. Quando o Sleep () State se estendeu, a junção () esperou que o thread termine ou o tempo de tempo ou o processamento de E/S tenha sido concluído, o thread reinseriu para o estado pronto.
5. Estado morto: o thread terminou de executar ou sair do método run () devido a uma exceção e o thread termina seu ciclo de vida.
Implementar Métodos de Threading Thread e Runnable
Tópico: herde a classe Thread, implemente o método de execução e chame o método de início na função principal para iniciar o thread
Runnable: interface, implementa a interface executável, passa como um parâmetro para o construtor de thread e chama o método de início no principal
exemplo:
classe Tarefa implementa Runnable {private int ticket = 10; @Override public void run () {for (int i = 0; i <20; i ++) {if (this.ticket> 0) {System.out.println (thread.currentThread (). GetName () + "ticket vendido" + this.Ticket--); }}}}}}; classe pública runnabletest {public static void main (string [] args) {task myTask = new Task (); Thread t1 = novo thread (myTask); Tópico T2 = novo thread (myTask); Thread t3 = novo thread (myTask); t1.start (); t2.start (); t3.start (); }} // threadTest.java Código fonte da classe Mythread estende thread {private int ticket = 10; public void run () {for (int i = 0; i <20; i ++) {if (this.ticket> 0) {System.out.println (this.getName () + "Ticket Sell: Ticket" + this.Ticket--); }}}} public class ThreadTest {public static void main (string [] args) {// Iniciar 3 threads t1, t2, t3; Cada tópico vende 10 ingressos cada! Mythread t1 = new mythread (); Mythread t2 = new mythread (); Mythread t3 = new mythread (); t1.start (); t2.start (); t3.start (); }};
A diferença entre thread e runnable
Thread é uma classe e o Runnable é uma interface; O Thread em si é uma classe que implementa a interface executável. Sabemos que "uma classe pode ter apenas uma classe pai, mas pode implementar várias interfaces", então o Runnable tem melhor escalabilidade. Além disso, o Runnable também pode ser usado para "compartilhar recursos". Ou seja, vários threads são criados com base em um determinado objeto executável e compartilharão recursos no objeto Runnable. Geralmente, é recomendável implementar multi-threading através do "Runnable"!
Run e começo de Thread
START (): sua função é iniciar um novo thread e o novo thread executará o método Run () correspondente. Start () não pode ser chamado repetidamente. Start () realmente inicia o thread através do método local START0 (). O start0 () executará um novo thread e o novo thread chamará o método run ().
RUN (): RUN () pode ser chamado repetidamente como métodos de membros comuns. Se você ligar para o RUN () separadamente, o RUN () será executado no thread atual e o novo thread não será iniciado! run () é chamar diretamente o método run () do membro executável do thread e não criar um novo thread.
// Demo.java Código -fonte do Mythread estende thread {public mythread (nome da string) {super (nome); } public void run () {System.out.println (thread.currentThread (). getName ()+"está em execução"); }}; public class Demo {public static void main (string [] args) {thread mythread = new mythread ("mythread"); System.out.println (thread.currentThread (). GetName ()+"ligue para mythread.run ()"); mythread.run (); System.out.println (thread.currentThread (). GetName ()+"ligue para mythread.start ()"); mythread.start (); }}Saída:
principal chamado mythread.run () main é o runningmain chamado mythread.start () mythread está executando
sincronizado
Em Java, cada objeto possui um bloqueio de sincronização. Quando chamamos o método sincronizado do objeto, o bloqueio do objeto é adquirido e o Syncronized (OBJ) adquire o bloqueio de sincronização do "objet Obj". Diferentes encadeamentos o acesso ao bloqueio de sincronização são mutuamente exclusivos. O bloqueio de sincronização do objeto só pode ser adquirido por um thread em um determinado momento. Através do bloqueio de sincronização, podemos obter acesso mutuamente exclusivo ao "objeto/método" em vários threads. Por exemplo, agora existem dois threads A e Thread B, que acessarão a "trava sincronizada do objeto Obj". Suponha que em algum momento a Thread A adquira o "Lock de sincronização do OBJ" e execute algumas operações; No momento, o Thread B também tenta adquirir o "Lock de sincronização do OBJ" - o Thread B falhará em adquirir, ele deve esperar até que o Thread A libera o "Lock de sincronização do OBJ" e só possa ser executado.
Regras básicas
Artigo 1: Quando um thread acessa o "método sincronizado" ou "bloco de código sincronizado" de "um determinado objeto", outros threads serão bloqueados do acesso ao "método sincronizado" ou "bloco de código sincronizado" de "o objeto".
Artigo 2: Quando um thread acessa o "método sincronizado" ou "bloco de código sincronizado" de "um determinado objeto", outros threads ainda podem acessar o bloco de código assincronizado de "este objeto".
Artigo 3: Quando um thread acessa o "método sincronizado" ou "bloco de código sincronizado" de "um determinado objeto", outros threads serão impedidos de acessar outros "métodos sincronizados" ou "bloco de código sincronizado" de "o objeto".
Método sincronizado
public sincronizado void foo1 () {System.out.println ("Método sincronizado");} Código sincronizado bloco public void foo2 () {sincronizado (this) {System.out.println ("Método sincronizado"); }}Isso no bloco de código sincronizado refere -se ao objeto atual. Isso também pode ser substituído por outros objetos, como esse é substituído pelo OBJ, o Foo2 () adquire o bloqueio de sincronização do OBJ quando sincronizado (OBJ).
Os blocos de código sincronizados podem controlar as áreas de acesso restrito a conflitos com mais precisão e, às vezes, executar com mais eficiência
Trava de instância e bloqueio global
Bloqueio de instância-bloqueado em um objeto de instância. Se a aula é um singleton, a fechadura também tem o conceito de uma trava global. A palavra -chave sincronizada corresponde ao bloqueio da instância.
Bloqueio global- esse bloqueio é direcionado para uma classe. Não importa quantos objetos seja a instância, os threads compartilham o bloqueio. O bloqueio global corresponde a sincronizado estático (ou bloqueado no objeto de classe ou carregador de classe desta classe).
classe pulbic algo {public sincronizado void ISSynca () {} public sincronizado void ISSYNCB () {} public Static Sincronized void csyncA () {} public estático vazio sincronizado csyncb () {}}}}}
(01) x.issynca () e x.issyncb () não podem ser acessados simultaneamente. Porque ISSynca () e ISSyncb () são bloqueios de sincronização que acessam o mesmo objeto (objeto x)!
(02) x.issynca () e y.issynca () podem ser acessados ao mesmo tempo. Como não está acessando o bloqueio de sincronização do mesmo objeto, x.issynca () acessa a trava de sincronização de x, enquanto y.issynca () acessa a trava de sincronização de y.
(03) x.csynca () e y.csyncb () não podem ser acessados simultaneamente. Como a csynca () e o csyncb () são tipos estáticos, x.csynca () é equivalente a algo.issynca () e y.csyncb () são equivalentes a algo.ISSYNCB (), eles compartilham um bloqueio de sincronização e não podem ser perguntados na mesma época.
(04) x.issynca () e something.csynca () podem ser acessados simultaneamente. Como o ISSYNCA () é um método de instância, o x.issynca () usa o bloqueio do objeto X; Enquanto o csynca () é um método estático, algo.csynca () pode entender que é um "bloqueio de classe" usado. Portanto, eles podem ser acessados simultaneamente.
Bloqueio de thread e despertar, notifique, notifiquell
Em Object.java, interfaces como wait (), notify () e notifyAll () são definidas. A função de wait () é deixar o encadeamento atual entrar em um estado de espera e espera () também permitirá que o encadeamento atual libere a trava que ele mantém. O papel de notify () e notifyAll () é acordar o tópico de espera no objeto atual; notify () é acordar um único thread, enquanto notifyAll () é acordar todos os threads.
Os detalhes da API sobre espera/acordar na aula de objeto são os seguintes:
notify () - Acorde um único thread aguardando neste monitor de objeto.
notifyAll () - Acorde todos os threads esperando neste monitor de objeto.
espera () - Coloque o thread atual em um "estado de espera (bloqueio)" e "até que outros threads chamem o método notify () ou notifyAll () desse objeto", e o thread atual é despertado (inserido no "estado pronto").
Espere (tempo limite longo) - Coloque o thread atual em um "estado de espera (bloqueio)" e "até que outros threads chamam o método notify () ou notifyAll () do objeto ou exceder a quantidade especificada de tempo" e o thread atual é despertado (inserido para o "estado pronto").
Espere (tempo limite longo, int nanos) - Que o tópico atual esteja em um "aguardar (bloquear) estado", "até que outro thread chamar o método notify () ou notifyAll (), ou algum outro thread interrompe o fio atual ou excedeu uma certa quantidade de tempo", e o fio atual é despertado (inserido para "Estado pronto").
// waittest.java Código -fonte do threada threada threads {public threada (nome da string) {super (nome); } public void run () {synchronized (this) {System.out.println (thread.currentThread (). getName ()+"Call notify ()"); // acorde o thread de espera atual notifica (); }}} classe pública waittest {public static void main (string [] args) {threada t1 = new ThreadA ("t1"); sincronizado (t1) {try {// iniciar "thread t1" System.out.println (thread.currentThread (). getName ()+"start t1"); t1.start (); // O thread principal aguarda o T1 acordar através do notify (). System.out.println (thread.currentThread (). GetName ()+"wait ()"); t1.wait (); System.out.println (thread.currentThread (). GetName ()+"continua"); } catch (interruptedException e) {e.printStackTrace (); }}}}Saída
Start principal t1main wait () T1 Call Notify () Principal Continuar
(01) Observe que o "thread principal" na figura representa o "thread principal principal". "Thread T1" representa "Thread T1" começou no Waittest. E "Lock" representa "Bloqueio síncrono do objeto T1".
(02) "Thread Main" cria novo "Thread T1" através do novo ThreadA ("T1"). Em seguida, a "trava síncrona do objeto T1" é obtida por meio de sincronizado (T1). Em seguida, ligue para t1.start () para iniciar "Thread T1".
(03) "Principal Thread" executa T1.wait () para liberar "Lock of T1 Object" e entra "Espere (bloqueando) Estado". Aguarde os threads em objetos T1 acordem -o via notify () ou notifyAll ().
(04) Depois que "Thread T1" é executado, a trava "do objeto atual" é obtida por meio de sincronizado (this); Em seguida, ligue para notify () para acordar o "Thread Withing no objeto atual", ou seja, acorde o "thread principal".
(05) Após a conclusão do "Thread T1", libere o "bloqueio do objeto atual". Imediatamente depois, o "thread principal" adquire o "bloqueio do objeto T1" e depois é executado.
t1.wait () é o método wait () chamado através de "Thread T1", mas o local onde o t1.wait () é chamado está em "thread principal principal". O encadeamento principal deve ser o "encadeamento atual", ou seja, o estado em execução, antes que o T1.Wait () possa ser executado. Portanto, o "thread atual" neste momento é o "Principal Main Main"! Portanto, o t1.wait () é fazer com que o "thread principal" espere, não "thread t1"!
pacote thread.test; classe pública notifyAltest {objeto estático privado obj = new Object (); public static void main (string [] args) {threada t1 = new Threada ("t1"); Threada T2 = new Threada ("T2"); Threada T3 = new Threada ("T3"); t1.start (); t2.start (); t3.start (); tente {System.out.println (thread.currentThread (). getName ()+"Sleep (3000)"); Thread.sleep (3000); } catch (interruptedException e) {e.printStackTrace (); } sincronizado (obj) {System.out.println (thread.currentThread (). getName ()+"notifyAll ()"); obj.notifyall (); // wake up t1.t2.t3 aqui}} classe estática threada estende thread {public threada (string name) {super (nome); } public void run () {synchronized (obj) {try {// Printout Result System.out.println (thread.currentThread (). getName () + "espera"); // libere o objeto obj bloqueio obj.wait (); // Printout Result System.out.println (thread.currentThread (). GetName () + "continua"); } catch (interruptedException e) {e.printStackTrace (); }}}}}} Saída:
T1 Waitmain Sleep (3000) T3 waitt2 waitmain notifyAll () t2 continue
(01) 3 threads "T1", "T2" e "T3" foram criados e iniciados no thread principal.
(02) O fio principal dorme por 3 segundos no sono (3000). Durante a linha principal, o sono por 3 segundos, assumimos que os três threads "T1", "T2" e "T3" estão todos em execução. Tome "T1" como exemplo. Quando for executado, ele executará obj.wait () para esperar que outros threads o acordem através do notify () ou NofityAll (); Da mesma forma, "T2" e "T3" também aguardarão outros threads para acordá -los através de Nofity () ou NofityAll ().
(03) O fio principal dorme por 3 segundos e depois corre. Execute obj.NotifyAll () para acordar o tópico de espera no OBJ, ou seja, acorde os três threads "T1", "T2" e "T3". Imediatamente após a execução do segmento principal (OBJ) do fio principal, o encadeamento principal libera o "OBJ Lock". Dessa maneira, "T1", "T2" e "T3" podem obter o "Obj Lock" e continuar a correr!
notificar, notificar todos e bloquear o relacionamento
Funções como wait (), notify () no objeto, como sincronizado, operarão em "Lock de sincronização de objetos".
espera () fará com que o "thread atual" espere. Como o encadeamento entra no estado de espera, o encadeamento deve liberar a "trava síncrona" mantida por sua trava, caso contrário, outros threads não poderão obter o "bloqueio síncrono" e não poderão executar!
Ok, depois que o tópico chama Wait (), ele liberará a "trava síncrona" mantida por sua fechadura; E, de acordo com a introdução anterior, sabemos que o tópico de espera pode ser despertado por notify () ou notifyAll (). Agora, por favor, pense em uma pergunta: o que é notify () com base no despertar do tópico de espera? Ou qual é a correlação entre espera () e notify ()? A resposta é: com base no "bloqueio de sincronização de objetos".
O segmento responsável por acordar o segmento de espera (chamamos de "encadeamento de despertar"), só pode acordar o segmento de espera depois de obter a "trava síncrona desse objeto" (o bloqueio de sincronização aqui deve ser o mesmo que o bloqueio de sincronização do segmento de espera) e chamando os métodos notify () ou notifyAll). Embora o tópico de espera seja despertado; No entanto, ele não pode ser executado imediatamente porque o thread de despertar ainda contém "bloqueio síncrono para o objeto". Você deve esperar até que o encadeamento de despertar libere o "bloqueio de sincronização do objeto" antes de obter o "bloqueio de sincronização do objeto" e continuar a ser executado.
Em resumo, notify (), espera () depende de "Lock Síncrono", que é mantido por bloqueios de objetos, e cada objeto tem e apenas um! É por isso que funções como notify (), wait () são definidas na classe de objeto, não na classe Thread.
Concessões de thread rendimento
As concessões de threads fazem com que o encadeamento mude do estado de execução para o estado pronto, para que outros threads de espera com a mesma prioridade possam obter direitos de execução; No entanto, não é garantido que, após o rendimento do encadeamento atual (), outros threads com a mesma prioridade definitivamente obterão direitos de execução; Também é possível que o thread atual entre no "estado em execução" e continue a ser executado.
rendimento e espere
(01) espera () é deixar o thread entrar no "aguardar (bloquear) o estado" do "estado em execução", enquanto não o rendimento () é deixar o thread entrar no "estado pronto" do "estado em execução".
(02) espera () é um bloqueio de sincronização que será lançado o objeto que ele mantém, enquanto o método de rendimento () não liberará o bloqueio.
(03) Espera é o método de objeto, o rendimento é o método de thread
Sleep Thread
A função do Sleep () é deixar o fio atual dormir, ou seja, o encadeamento atual entrará do "estado em execução" para o "estado de sono (bloqueio)". O sono () especificará o tempo de sono e o tempo de sono do fio será maior que/igual ao tempo de sono; Quando o tópico for despertado novamente, ele mudará de um "estado de bloqueio" para um "estado pronto", aguardando a programação da CPU.
A diferença entre dormir e esperar
A função de wait () é permitir que o encadeamento atual entre no "aguarde (bloquear) do" estado em execução "e também liberar o bloqueio de sincronização. A função do sono () é deixar o encadeamento atual entrar no" sono (bloqueio) do "estado de corrida". (Isso na verdade não é muito diferente)
espera () libera o bloqueio de sincronização do objeto, enquanto o sono () não libera o bloqueio
Espera é o método de objeto, o sono é o método de thread
Juntar
Deixe o thread principal esperar e o thread infantil pode continuar funcionando após a conclusão do thread principal.
interromper
Usado para encerrar um fio bloqueado
@OverridePublic void run () {try {while (true) {// Execute a tarefa ...}} Catch (interruptedException ie) {// Devido a uma exceção interrompida de exceção, saia do loop (true) e o thread termina! }}Em while (true), a chamada para interromper () do encadeamento gera uma interrupção interruptException. A captura interrompida está do lado de fora enquanto (verdadeira), saindo assim do laço (verdadeiro)
Termina um tópico no estado de corrida
@OverridePublic void run () {while (! IsInterrupted ()) {// Execute Task ...}}Maneira comum de encerrar os threads
@OverridePublic void run () {try {// 1. IsInterrupted () garante que o thread será encerrado enquanto a interrupção estiver marcada. while (! isInterrupted ()) {// Execute Task ...}} Catch (interruptedException ie) {// 2. Exceção de interrupções de exceção garante que, quando ocorre uma exceção interrompida, o encadeamento é encerrado. }}
Prioridade do tópico
O intervalo de prioridade do thread em Java é de 1 a 10 e a prioridade padrão é 5. "Trentos de alta prioridade" precederão a execução por "threads de baixa prioridade". Existem dois tipos de threads no Java: Tópico do usuário e thread Daemon. Eles podem ser distinguidos pelo método iSdaemon (): se false for retornado, significa que o thread é um "thread do usuário"; Caso contrário, é um "Thread Daemon". Os threads do usuário geralmente executam tarefas no nível do usuário, enquanto os threads Daemon também são "threads de back-end", que geralmente são usados para executar tarefas em segundo plano. Deve -se notar que a máquina virtual Java sairá após a conclusão do "thread do usuário".
Cada encadeamento tem uma prioridade. "Trentos de alta prioridade" precederão a execução por "threads de baixa prioridade". Cada encadeamento pode ser marcado como daemon ou não-daemon. Ao criar um novo thread infantil em algum tópico principal em execução, a prioridade do thread infantil é definida como igual a "prioridade do thread principal que o criou", e "o encadeamento filho será o thread Daemon" quando e somente se "o thread principal criado é um thread Daemon".
Quando uma máquina virtual Java é iniciada, geralmente há um único thread não daemon (este thread é iniciado através do método principal ()). A JVM será executada até que qualquer uma das seguintes condições ocorra e a JVM encerrará a execução:
(01) O método EXIT () é chamado e EXIT () tem permissão para ser executado normalmente.
(02) Todos os "threads não daemon" estão mortos (ou seja, existem apenas "threads daemon" na JVM).
Daemon
(01) O thread principal principal é o thread do usuário, e o thread Child T1 que ele cria também é o thread do usuário.
(02) T2 é o fio daemon. Quando o "thread principal principal" e "sub-thread T1" (ambos são threads de usuário) são executados e apenas o thread daemon T2 é deixado, a JVM sai automaticamente.
Problemas de produtor e consumidor
(01) O produtor só produz quando o armazém não está cheio e interrompe a produção quando o armazém está cheio.
(02) Os consumidores só podem consumir quando possuem produtos em armazenamento e aguardam se tiverem armazéns vazios.
(03) Quando os consumidores acham que não há produto para consumir no armazém, eles notificarão o produtor.
(04) Quando os produtores produzem produtos consumíveis, eles devem notificar os consumidores em espera para consumir.
Comunicação entre threads
Método: Memória compartilhada e mensagens
Memória compartilhada: Thread A e Thread B Compartilhe a memória, Thread A Atualiza o valor da variável compartilhada, a atualiza para a memória principal e o encadeamento B vai para a memória principal para ler as variáveis atualizadas do thread A. Todo o processo de comunicação deve passar pela memória principal. A sincronização é realizada explicitamente.
Se uma variável for do tipo volátil, a leitura e a gravação da variável serão atômicas. Se forem várias operações voláteis ou operações compostas semelhantes a ++ voláteis, essas operações não são atômicas na íntegra.
A variável volátil em si tem as seguintes características:
[Visibilidade]: Ao ler uma variável volátil, você sempre pode ver a última gravação na variável volátil (qualquer encadeamento).
[Atomicidade]: possui atomicidade para a leitura/gravação de uma única variável volátil, mas não possui atomicidade para operações compostas semelhantes ao volátil ++.
Escrita volátil: Ao escrever uma variável volátil, o JMM liberará a variável compartilhada na memória local correspondente ao encadeamento à memória principal.
Leia volátil: Ao ler uma variável volátil, o JMM invalidará a memória local correspondente ao thread. O thread lerá a variável compartilhada da memória principal.
Entrega de mensagens: o envio de uma mensagem é executado implicitamente antes que a mensagem seja aceita.
Threadlocal
Threadlocal não é usado para resolver o problema do acesso de vários thread a objetos compartilhados. De um modo geral, o objeto para o thread através do threadlocal.set () é um objeto usado pelo próprio thread. Outros tópicos não precisam ser acessados e não podem ser acessados. Threadlocal permite que cada encadeamento mantenha seu próprio objeto independente. Ele não é implementado através do ThreadLocal.Set (), mas um objeto criado pela operação do novo objeto em cada thread. Cada encadeamento cria um, não uma cópia ou cópia do objeto. A referência ao objeto recém -criado é salvo no mapa de cada thread através do ThreadLocal.Set (). Cada thread possui esse mapa. Quando threadlocal.get () é executado, cada thread retira o objeto colocado de seu próprio mapa. Portanto, o que é retirado é o objeto em cada thread. A instância Threadlocal é usada como a chave do mapa. Se a coisa que o ThreadLocal.Set () entra é o mesmo objeto compartilhado por vários threads, o ThreadLocal.get () de vários threads ainda obtém o próprio objeto compartilhado e ainda existe um problema de acesso simultâneo.
Uma implementação do threadlocal
importar java.util.Collections; importar java.util.hashmap; importar java.util.map; /** * classe usando threadlocal * * @author leizhimin 2010-1-5 10:35:27 */public classe mythreadlocal {// define uma variável Threadlocal para salvar ou interno de dados privados com.Lavasoft.test2.ThreadLocal <Integher> tl = new Com.Lavs.Tasoft.Test2.ThreadLocal <Integher> tl = new.law.Lavs.Tasoft.Test2.ThreadLocal <Integer> Inteiro InitialValue () {return 0; }}; Public Integer GetNextNum () {// Obtenha o valor de TL e adicione 1 e atualize o valor de T1 tl.set (tl.get () + 1); retornar tl.get (); }} classe ThreadLocal <T> {mapa privado <thread, t> map = collection.synchronizedmap (novo hashmap <thread, t> ()); public threadlocal () {} protegido t InitialValue () {return null; } public t get () {thread t = thread.currentThread (); T obj = map.get (t); if (obj == null &&! map.containsKey (t)) {obj = inicialValue (); map.put (t, obj); } retornar obj; } public void set (valor t) {map.put (thread.currentThread (), valor); } public void remover () {map.remove (thread.currentThread ()); }}De fato, Threadlocal faz isso:
public t get () {thread t = thread.currentThread (); Threadlocalmap map = getMap (t); if (map! = null) {threadlocalmap.entry e = map.getEntry (this); if (e! = nulo) retornar (t) e.value; } retornar setInitialValue (); }