Java 如何阻止我的程序永远等待?(等待/通知多线程问题)

Java 如何阻止我的程序永远等待?(等待/通知多线程问题),java,multithreading,Java,Multithreading,我有三个类,一个用来表示一堆URL private Queue<String> queue = new LinkedList<String>(); public Queue<String> getQueue() { return queue; } private int limit = 5; private int stillParsing; public synchronized Stri

我有三个类,一个用来表示一堆URL

    private Queue<String> queue = new LinkedList<String>();

    public Queue<String> getQueue() {
        return queue;
    }

    private int limit = 5;
    private int stillParsing;

    public synchronized String getNextString() throws InterruptedException {
        while (queue.isEmpty()||stillParsing > limit) {
            System.out.println("no for you "+ queue.peek());
            wait();
        }

        System.out.println("grabbed");

        notify();
        stillParsing++;
        System.out.println(queue.peek());
        return queue.remove();

    }

    public synchronized void doneParsing() {
        stillParsing--;
    }

}
还有一个映射器,它使用这个snipet将对象添加到URL堆中

while (urls.hasMoreTokens()) {
                try{

                    word.set(urls.nextToken());
                String currenturl = word.toString();
                System.out.println(currenturl);
                pile.getQueue().add(currenturl);

通过调试,我认为发生的情况是,在映射程序有机会填充队列之前,所有线程都试图立即从队列中获取,并且它们被卡住等待。不幸的是,所有等待的线程都导致我的程序挂起,无法向队列添加更多URL。我应该如何着手处理这个问题?最好在仍然使用wait-notify时使用。

即使没有阅读所有代码行和解释,我也可以说,wait和notify的用法有缺陷

方法
wait()
正在阻塞。仅当调用同一监视器上的
notify()
时,它才会退出。这意味着您不能同时从同一线程放置
wait()
notify()
。您根本无法到达
notify()
,因为
wait()
被永远阻止

wait()
wait(timeout)
的其他版本被阻止,但受到指定超时的限制。 此外,等待/通知对仅在写入
synchronized
块时工作:

// thread-1
synchronoized(obj) {
    obj.wait();
} 


// thread-2
synchronoized(obj) {
    obj.notify();
} 

当线程2调用notify时,线程1将退出等待

即使没有阅读所有代码行和解释,我也可以说您对wait和notify的使用是错误的

while (urls.hasMoreTokens()) {
    try {
       word.set(urls.nextToken());
       String currenturl = word.toString();
       System.out.println(currenturl);
       pile.getQueue().add(currenturl);
方法
wait()
正在阻塞。仅当调用同一监视器上的
notify()
时,它才会退出。这意味着您不能同时从同一线程放置
wait()
notify()
。您根本无法到达
notify()
,因为
wait()
被永远阻止

wait()
wait(timeout)
的其他版本被阻止,但受到指定超时的限制。 此外,等待/通知对仅在写入
synchronized
块时工作:

// thread-1
synchronoized(obj) {
    obj.wait();
} 


// thread-2
synchronoized(obj) {
    obj.notify();
} 
当线程2调用notify时,线程1将退出等待

while (urls.hasMoreTokens()) {
    try {
       word.set(urls.nextToken());
       String currenturl = word.toString();
       System.out.println(currenturl);
       pile.getQueue().add(currenturl);
在上面的代码中,您通过在队列中添加一些内容而不使用pile的方法,打破了对pile的封装。在这个类中不应该有
getQueue()
方法:对这个共享数据结构的所有访问都应该在同一个锁上同步。因此,您应该添加一个允许向队列添加URL的同步方法。此方法还应调用
notify()
(或更好的调用:
notifyAll()
),以便唤醒正在等待队列中某个元素的线程:

public synchronized void addUrl(String url) {
    queue.add(url);
    notifyAll();
}
在上面的代码中,您通过在队列中添加一些内容而不使用pile的方法,打破了对pile的封装。在这个类中不应该有
getQueue()
方法:对这个共享数据结构的所有访问都应该在同一个锁上同步。因此,您应该添加一个允许向队列添加URL的同步方法。此方法还应调用
notify()
(或更好的调用:
notifyAll()
),以便唤醒正在等待队列中某个元素的线程:

public synchronized void addUrl(String url) {
    queue.add(url);
    notifyAll();
}

你说得对。使用并发队列。Java为您提供了在
Java.util.concurrent
包中执行类似操作所需的所有工具。您是否能够使用
BlockingQueue
而不是
队列
,我仍然想知道为什么我所拥有的不起作用。当您通过
getQueue()
公开
队列时,您的代码一开始就不是线程安全的。您是正确的。使用并发队列。Java为您提供了在
Java.util.concurrent
包中执行类似操作所需的所有工具。您是否能够使用
BlockingQueue
而不是
队列
,不过我还是想知道为什么我的东西不起作用。当你通过
getQueue()
暴露
队列时,你的代码一开始就不是线程安全的。此外,
notify
很少是正确的--
notifyAll
通常是正确性所必需的,以防止唤醒被吞没。@Tom G,这取决于你的申请。通常您只想唤醒一个线程。让我重新表述一下——使用
notify
需要格外小心,因为您无法控制哪个线程被唤醒,需要额外的工作来确保只有正确的线程才能获取对象的监视器。此外,
notify
很少是正确的--
notifyAll
通常是正确性所必需的,以防止唤醒被吞没。@Tom G,这取决于您的应用程序。通常您只想唤醒一个线程。让我重新表述一下——使用
notify
需要格外小心,因为您无法控制哪个线程被唤醒,并且需要额外的工作来确保只有正确的线程才能获取对象的监视器。