如何在Java中使用wait和notify而不出现IllegalMonitorStateException?
我有 2 个矩阵,我需要将它们相乘,然后打印每个单元格的结果。 一旦一个单元格准备好,我就需要打印它,但例如,我需要在单元格 [2][0] 之前打印 [0][0] 单元格,即使 [2][0] 的结果先准备好。 所以我需要按订单打印。 所以我的想法是让打印机线程等待,直到 multiplyThread
通知它正确的单元格已准备好打印,然后 printerThread
将打印该单元格并返回等待等等..
所以我有一个执行乘法的线程:
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();
}
打印每个单元格结果的线程:
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] + " ");
}
}
}
现在它抛出了这些异常:
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)
multiplyThread
中的第49行是“notify()” ..我认为我需要以不同的方式使用同步,但我不确定如何使用。
如果有人可以帮助这段代码工作,我将非常感激。
I have 2 matrices and I need to multiply them and then print the results of each cell. As soon as one cell is ready I need to print it, but for example I need to print the [0][0] cell before cell [2][0] even if the result of [2][0] is ready first. So I need to print it by order.
So my idea is to make the printer thread wait until the multiplyThread
notifies it that the correct cell is ready to be printed and then the printerThread
will print the cell and go back to waiting and so on..
So I have this thread that does the multiplication:
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();
}
Thread that prints the result of each cell:
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] + " ");
}
}
}
Now it throws me these exceptions:
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)
line 49 in multiplyThread
is the "notify()"..I think I need to use the synchronized differently but I am not sure how.
If anyone can help this code to work I will really appreciate it.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(12)
能够调用 notify( ) 你需要在同一个对象上同步。
To be able to call notify() you need to synchronize on the same object.
在 Java 中使用
wait
和notify
或notifyAll
方法时,必须记住以下事项:notifyAll
而不是如果您预计有多个线程正在等待锁定,请通知
。wait
和 < code>notify 方法必须在同步上下文中调用。 请参阅链接以获取更详细的说明。wait()
和notify()
方法; 每个对象都有自己的锁,因此在对象 A 上调用wait()
并在对象 B 上调用notify()
没有任何意义。While using the
wait
andnotify
ornotifyAll
methods in Java the following things must be remembered:notifyAll
instead ofnotify
if you expect that more than one thread will be waiting for a lock.wait
andnotify
methods must be called in a synchronized context. See the link for a more detailed explanation.wait()
method in a loop because if multiple threads are waiting for a lock and one of them got the lock and reset the condition, then the other threads need to check the condition after they wake up to see whether they need to wait again or can start processing.wait()
andnotify()
method; every object has its own lock so callingwait()
on object A andnotify()
on object B will not make any sense.你需要把这个线程化吗? 我想知道你的矩阵有多大,以及让一个线程打印而另一个线程执行乘法是否有任何好处。
也许在进行相对复杂的线程工作之前测量一下这个时间是值得的?
如果您确实需要对其进行线程化,我将创建“n”个线程来执行单元格的乘法(也许“n”是您可用的核心数量),然后使用 ExecutorService 和 Future 同时调度多个乘法的机制。
这样您就可以根据核心数量来优化工作,并且您可以使用更高级别的 Java 线程工具(这应该会让生活变得更轻松)。 将结果写回接收矩阵,然后在所有未来任务完成后简单地打印出来。
Do you need to thread this at all ? I'm wondering how big your matrices are, and whether there's any benefit in having one thread print whilst the other does the multiplication.
Perhaps it would be worth measuring this time before doing the relatively complex threading work ?
If you do need to thread it, I would create 'n' threads to perform the multiplication of the cells (perhaps 'n' is the number of cores available to you), and then use the ExecutorService and Future mechanism to dispatch multiple multiplications simultaneously.
That way you can optimise the work based on the number of cores, and you're using the higher level Java threading tools (which should make life easier). Write the results back into a receiving matrix, and then simply print this once all your Future tasks have completed.
假设您有一个“黑盒”应用程序,其中包含一些名为
BlackBoxClass
的类,该类具有方法doSomething();
。此外,您还有名为
onResponse(String resp)
的观察者或侦听器,将在未知时间后由BlackBoxClass
调用。流程很简单:
假设我们不知道
BlackBoxClass
发生了什么,也不知道何时应该得到答案,但您不想继续编写代码,直到得到答案或换句话说得到答案onResponse
调用。 这里输入“同步助手”:现在我们可以实现我们想要的:
Let's say you have 'black box' application with some class named
BlackBoxClass
that has methoddoSomething();
.Further, you have observer or listener named
onResponse(String resp)
that will be called byBlackBoxClass
after unknown time.The flow is simple:
Lets say we don't know what is going on with
BlackBoxClass
and when we should get answer but you don't want to continue your code till you get answer or in other word getonResponse
call. Here enters 'Synchronize helper':Now we can implement what we want:
您只能对您拥有其监视器的对象调用通知。 所以你需要类似的东西
You can only call notify on objects where you own their monitor. So you need something like
notify()
也需要同步notify()
needs to be synchronized as well我将通过简单的示例向您展示在 Java 中使用
wait
和notify
的正确方法。因此,我将创建两个名为 ThreadA 和 ThreadA 的类。 线程B。 线程A将调用线程B。
对于 ThreadB 类:
I'll right simple example show you the right way to use
wait
andnotify
in Java.So I'll create two class named ThreadA & ThreadB. ThreadA will call ThreadB.
and for Class ThreadB:
如果您想选择如何执行线程,则可以简单使用:-
Simple use if you want How to execute threads alternatively :-
我们可以调用notify来恢复等待对象的执行,就像
通过调用同一类的另一个对象上的notify来恢复this一样
we can call notify to resume the execution of waiting objects as
resume this by invoking notify on another object of same class
对于这个特定的问题,为什么不将各种结果存储在变量中,然后当处理最后一个线程时,您可以以任何您想要的格式打印。 如果您要在其他项目中使用您的工作历史记录,这尤其有用。
For this particular problem, why not store up your various results in variables and then when the last of your thread is processed you can print in whatever format you want. This is especially useful if you are gonna be using your work history in other projects.
这看起来像是生产者-消费者模式的情况。 如果您使用的是 java 5 或更高版本,您可以考虑使用阻塞队列(java.util.concurrent.BlockingQueue)并将线程协调工作留给底层框架/api 实现。
请参阅示例
爪哇5:
http://docs.oracle.com /javase/1.5.0/docs/api/java/util/concurrent/BlockingQueue.html
或 java 7(同一示例):
http://docs.oracle.com/javase /7/docs/api/java/util/concurrent/BlockingQueue.html
This looks like a situation for producer-consumer pattern. If you’re using java 5 or up, you may consider using blocking queue(java.util.concurrent.BlockingQueue) and leave the thread coordination work to the underlying framework/api implementation.
See the example from
java 5:
http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/BlockingQueue.html
or java 7 (same example):
http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/BlockingQueue.html
当您使用
synchronized(this)
调用wait()
方法时,您已经正确保护了代码块。但是,当您在不使用受保护块的情况下调用
notify()
方法时,您没有采取相同的预防措施:synchronized(this)
或synchronized(someObject)
如果您参考 Object 上的 Oracle 文档页面类,其中包含
wait()
、notify()
、notifyAll()
方法,您可以在这三个方法中看到以下注意事项在过去 7 年中,许多事情发生了变化,让我们在下面的 SE 问题中研究一下
synchronized
的其他替代方案:如果可以使用synchronized(this),为什么还要使用ReentrantLock?
同步与锁定
避免在 Java 中使用同步(this)?
You have properly guarded your code block when you call
wait()
method by usingsynchronized(this)
.But you have not taken same precaution when you call
notify()
method without using guarded block :synchronized(this)
orsynchronized(someObject)
If you refer to oracle documentation page on Object class, which contains
wait()
,notify()
,notifyAll()
methods, you can see below precaution in all these three methodsMany things have been changed in last 7 years and let's have look into other alternatives to
synchronized
in below SE questions:Why use a ReentrantLock if one can use synchronized(this)?
Synchronization vs Lock
Avoid synchronized(this) in Java?