我有一个具有以下两种方法的线程类:
public void run()
{
boolean running=true;
while(running)
{
sendImage();
}
}
private synchronized void sendImage()
{
if(!imageready.getFlag())
{
try
{
wait();
System.out.println("woke up!");
}
catch(Exception e)
{
System.out.println("Exception raises in ImgSender while waiting");
}
}
else
{
//send image
}
}
我还有一个GUI部分,用鼠标点击方法打开文件选择器窗口让用户选择文件。代码
public void mouseClicked (MouseEvent event)
{
chooser=new JFileChooser();
int status=chooser.showOpenDialog(null);
if (status == JFileChooser.APPROVE_OPTION)
{
try
{
prepareImage();
}
catch(Exception e)
{
System.out.println("file not opened");
}
}
}
private synchronized void prepareImage() throws Exception
{
System.out.println("File chosen");
imgFile=chooser.getSelectedFile();
image.setImg( ImageIO.read(imgFile) );
imageready.setFlag(true);
notifyAll();
System.out.println("noticed other threads");
}
但我无法使用notifyAll()唤醒第一个线程,以便它可以发送图像。
答案 0 :(得分:1)
正如@MadProgrammer所提到的,你没有在同一个锁上同步。锁是,不知道如何描述它。这是一把锁。要在Java中锁定和等待,您选择一个对象来表示" lock"。
如果2个线程在2个不同的对象上同步,它就像第一个线程说的那样#34;我在泵#1中抽气,如果你需要使用它,那么就行了#34;然后第二个帖子说"嘿,让我知道你何时完成#2" (当泵2停止运行时)。
如果你想让第二个驾驶员等待第一个驾驶员完成抽水,那么他需要申报对#1泵的兴趣,这是其他人持有的泵。同样,如果您希望2个线程成功执行等待和通知,则需要引用相同的对象。
为什么在您的情况下这可能会让您感到困惑,因为您没有指定显式对象来锁定。您将方法声明为synchronized
,它隐式使用方法正在执行的对象的实例作为锁定资源。
public class LockTest implements Runnable {
public void synchronized doNothing() {
try {
System.out.println("Starting lock...");
Thread.sleep(5000);
System.out.println("Releasing lock...");
}
catch (InterruptedException e) {
}
}
public static void main(String[] args) {
LockTest test1 = new LockTest();
LockTest test2 = new LockTest();
new Thread(test1).start();
new Thread(test2).start();
// Notice from the output that the threads do not block each other.
}
}
我们创建了2个LockTest
个实例,因此它们不会相互阻塞,因为它们具有完全独立的锁定。
public class LockTest implements Runnable {
private Object thingToLockWith;
public LockTest(Object thingToLockWith) {
this.thingToLockWith = thingToLockWith;
}
public void doNothing() {
synchronized (thingToLockWith) {
try {
System.out.println("Starting lock...");
Thread.sleep(5000);
System.out.println("Releasing lock...");
}
catch (InterruptedException e) {
}
}
}
public static void main(String[] args) {
Object lock = new Object();
LockTest test1 = new LockTest(lock);
LockTest test2 = new LockTest(lock);
new Thread(test1).start();
new Thread(test2).start();
// Notice from the output they block.
}
了解输出的不同之处。第二个线程必须排队等待第一个线程。
答案 1 :(得分:0)
不要在Swing应用程序中直接使用线程API,而是使用Swing workers,只需在需要执行后台任务时创建一个实例,比如发送图像而你不想阻止GUI线程
答案 2 :(得分:0)
看来你正在等待一个线程对象,而gui对象正在进行通知。
所以当你做notifyAll();
时,不要指望等待线程对象唤醒,因为这是一个完全不同的锁。
你可以使用一个普通的锁。