Eu tenho 2 matrizes e preciso multiplicá-las e depois imprimir os resultados de cada célula. Assim que uma célula estiver pronta, preciso imprimi-la, mas, por exemplo, preciso imprimir a célula [0] [0] antes da célula [2] [0], mesmo que o resultado de [2] [0] esteja pronto primeiro . Então, eu preciso imprimi-lo por encomenda. Então, minha idéia é fazer com que o encadeamento da impressora aguarde até multiplyThread
que ele notifique que a célula correta está pronta para ser impressa e, em seguida printerThread
, imprima a célula e volte a aguardar e assim por diante.
Então, eu tenho esse segmento que faz a multiplicação:
public void run()
{
int countNumOfActions = 0; // How many multiplications have we done
int maxActions = randomize(); // Maximum number of actions allowed
for (int i = 0; i < size; i++)
{
result[rowNum][colNum] = result[rowNum][colNum] + row[i] * col[i];
countNumOfActions++;
// Reached the number of allowed actions
if (countNumOfActions >= maxActions)
{
countNumOfActions = 0;
maxActions = randomize();
yield();
}
}
isFinished[rowNum][colNum] = true;
notify();
}
Segmento que imprime o resultado de cada célula:
public void run()
{
int j = 0; // Columns counter
int i = 0; // Rows counter
System.out.println("The result matrix of the multiplication is:");
while (i < creator.getmThreads().length)
{
synchronized (this)
{
try
{
this.wait();
}
catch (InterruptedException e1)
{
}
}
if (creator.getmThreads()[i][j].getIsFinished()[i][j] == true)
{
if (j < creator.getmThreads()[i].length)
{
System.out.print(creator.getResult()[i][j] + " ");
j++;
}
else
{
System.out.println();
j = 0;
i++;
System.out.print(creator.getResult()[i][j] + " ");
}
}
}
Agora isso me lança essas exceções:
Exception in thread "Thread-9" java.lang.IllegalMonitorStateException
at java.lang.Object.notify(Native Method)
at multiplyThread.run(multiplyThread.java:49)
Exception in thread "Thread-6" Exception in thread "Thread-4" java.lang.IllegalMonitorStateException
at java.lang.Object.notify(Native Method)
at multiplyThread.run(multiplyThread.java:49)
java.lang.IllegalMonitorStateException
at java.lang.Object.notify(Native Method)
at multiplyThread.run(multiplyThread.java:49)
Exception in thread "Thread-5" java.lang.IllegalMonitorStateException
at java.lang.Object.notify(Native Method)
at multiplyThread.run(multiplyThread.java:49)
Exception in thread "Thread-8" java.lang.IllegalMonitorStateException
at java.lang.Object.notify(Native Method)
at multiplyThread.run(multiplyThread.java:49)
Exception in thread "Thread-7" java.lang.IllegalMonitorStateException
at java.lang.Object.notify(Native Method)
at multiplyThread.run(multiplyThread.java:49)
Exception in thread "Thread-11" java.lang.IllegalMonitorStateException
at java.lang.Object.notify(Native Method)
at multiplyThread.run(multiplyThread.java:49)
Exception in thread "Thread-10" java.lang.IllegalMonitorStateException
at java.lang.Object.notify(Native Method)
at multiplyThread.run(multiplyThread.java:49)
Exception in thread "Thread-12" java.lang.IllegalMonitorStateException
at java.lang.Object.notify(Native Method)
at multiplyThread.run(multiplyThread.java:49)
a linha 49 multiplyThread
é o "notify ()". Acho que preciso usar o sincronizado de maneira diferente, mas não sei como.
Se alguém puder ajudar esse código a funcionar, eu realmente aprecio isso.
fonte
while(!JobCompleted);
opção é geralmente uma má idéia porque ele amarra o seu CPU em 100% a verificação da mesma variável constante (ver aqui )while(!JobCompleted) Thread.sleep(5);
não tem esse problema #wait
sempre que o encadeamento atual tiver um bloqueio no objeto no qualwait
é chamado. Se você usa umsynchronized
bloco ou um método sincronizado, é com você.Ao usar os métodos
wait
enotify
ounotifyAll
em Java, as seguintes coisas devem ser lembradas:notifyAll
vez denotify
se você espera que mais de um encadeamento esteja esperando por um bloqueio.wait
enotify
devem ser chamados em um contexto sincronizado . Veja o link para uma explicação mais detalhada.wait()
método em um loop, porque se vários threads estiverem aguardando um bloqueio e um deles tiver o bloqueio e redefinir a condição, os outros threads precisarão verificar a condição depois de acordarem para ver se precisam esperar novamente ou pode iniciar o processamento.wait()
enotify()
método; todo objeto tem seu próprio bloqueio, portanto, chamar owait()
objeto A e onotify()
objeto B não fará nenhum sentido.fonte
Você precisa enfiar isso? Eu estou querendo saber o tamanho das suas matrizes e se há algum benefício em imprimir um thread enquanto o outro faz a multiplicação.
Talvez valesse a pena medir esse tempo antes de executar o trabalho de rosqueamento relativamente complexo?
Se você precisar encadear, eu criaria 'n' threads para executar a multiplicação das células (talvez 'n' seja o número de núcleos disponíveis para você) e, em seguida, use o mecanismo ExecutorService and Future para despachar várias multiplicações simultaneamente .
Dessa forma, você pode otimizar o trabalho com base no número de núcleos e usar as ferramentas de encadeamento Java de nível superior (o que deve facilitar a vida). Escreva os resultados novamente em uma matriz de recebimento e, em seguida, simplesmente imprima isso quando todas as suas tarefas futuras forem concluídas.
fonte
Digamos que você tenha o aplicativo 'black box' com alguma classe nomeada
BlackBoxClass
que possui métododoSomething();
.Além disso, você tem um observador ou ouvinte chamado
onResponse(String resp)
que será chamadoBlackBoxClass
após um tempo desconhecido.O fluxo é simples:
Digamos que não sabemos o que está acontecendo
BlackBoxClass
e quando devemos obter resposta, mas você não deseja continuar seu código até receber resposta ou, em outras palavras, receber umaonResponse
ligação. Aqui entra 'Synchronize helper':Agora podemos implementar o que queremos:
fonte
Você só pode ligar para notificar sobre objetos onde possui o monitor deles. Então você precisa de algo como
fonte
notify()
precisa ser sincronizado tambémfonte
Vou mostrar um exemplo simples da maneira correta de usar
wait
enotify
em Java. Então, eu vou criar duas classes denominadas ThreadA e ThreadB . ThreadA chamará ThreadB.e para a classe ThreadB:
fonte
Uso simples se você quiser Como executar threads alternativamente: -
fonte
podemos ligar para notificar para retomar a execução de objetos em espera como
retome isso chamando notificar em outro objeto da mesma classe
fonte
Para esse problema específico, por que não armazenar seus vários resultados em variáveis e, quando o último de seu thread for processado, você poderá imprimir no formato que desejar. Isso é especialmente útil se você estiver usando seu histórico de trabalho em outros projetos.
fonte
Parece uma situação para o padrão produtor-consumidor. Se você estiver usando o java 5 ou superior, considere o uso da fila de bloqueio (java.util.concurrent.BlockingQueue) e deixe o trabalho de coordenação do encadeamento na implementação subjacente da estrutura / API. Veja o exemplo do java 5: http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/BlockingQueue.html ou java 7 (mesmo exemplo): http: // docs. oracle.com/javase/7/docs/api/java/util/concurrent/BlockingQueue.html
fonte
Você protegeu adequadamente seu bloco de código ao chamar o
wait()
método usandosynchronized(this)
.Mas você não tomou a mesma precaução ao chamar o
notify()
método sem usar o bloco protegido:synchronized(this)
ousynchronized(someObject)
Se você consultar a página de documentação do Oracle no objeto classe, que contém
wait()
,notify()
,notifyAll()
métodos, você pode ver abaixo precaução em todos esses três métodosMuitas coisas foram alteradas nos últimos 7 anos e vamos procurar outras alternativas para as
synchronized
perguntas abaixo do SE:Por que usar um ReentrantLock se é possível usar sincronizado (isso)?
Sincronização vs Bloqueio
Evitar sincronizado (isso) em Java?
fonte