質問:
- 最後の要素を削除しようとすると NoSuchElementException が発生するのはなぜですか?
- どうすれば修正できますか?
LinkedList に整数を追加/削除する 3 つのクラス (以下を参照) があります。削除するスレッドが最後の要素に到達するまで、すべてが正常に機能します。
両方のスレッドがそれを削除しようとしているようです。最初のものは成功しますが、2 番目のものはできません。しかし、私は synchronized-method/synchroniced-attribute +!sharedList.isEmpty()
がそれを処理すると思っていました。
Class Producer: このクラスは、乱数を作成し、それらをsharedListに入れ、数値を追加したことをコンソールに書き込み、中断されると停止することになっています。このクラスのスレッドは 1 つだけ必要です。
import java.util.LinkedList;
public class Producer extends Thread
{
private LinkedList sharedList;
private String name;
public Producer(String name, LinkedList sharedList)
{
this.name = name;
this.sharedList = sharedList;
}
public void run()
{
while(!this.isInterrupted())
{
while(sharedList.size() < 100)
{
if(this.isInterrupted())
{
break;
} else
{
addElementToList();
}
}
}
}
private synchronized void addElementToList()
{
synchronized(sharedList)
{
sharedList.add((int)(Math.random()*100));
System.out.println("Thread " + this.name + ": " + sharedList.getLast() + " added");
}
try {
sleep(300);
} catch (InterruptedException e) {
this.interrupt();
}
}
}
クラス Consumer:このクラスは、sharedList に最初の要素が存在する場合、それを削除することになっています。実行は、 sharedListが空になるまで (中断された後) 続行する必要があります。このクラスの複数 (少なくとも 2 つ) のスレッドが必要です。
import java.util.LinkedList;
public class Consumer extends Thread
{
private String name;
private LinkedList sharedList;
public Consumer(String name, LinkedList sharedList)
{
this.name = name;
this.sharedList = sharedList;
}
public void run()
{
while(!this.isInterrupted())
{
while(!sharedList.isEmpty())
{
removeListElement();
}
}
}
private synchronized void removeListElement()
{
synchronized(sharedList)
{
int removedItem = (Integer) (sharedList.element());
sharedList.remove();
System.out.println("Thread " + this.name + ": " + removedItem + " removed");
}
try {
sleep(1000);
} catch (InterruptedException e) {
this.interrupt();
}
}
}
Class MainMethod:このクラスは、スレッドを開始および中断することになっています。
import java.util.LinkedList;
public class MainMethod
{
public static void main(String[] args) throws InterruptedException
{
LinkedList sharedList = new LinkedList();
Producer producer = new Producer("producer", sharedList);
producer.start();
Thread.sleep(1000);
Consumer consumer1 = new Consumer("consumer1", sharedList);
Consumer consumer2 = new Consumer("consumer2", sharedList);
consumer1.start();
consumer2.start();
Thread.sleep(10000);
producer.interrupt();
consumer1.interrupt();
consumer2.interrupt();
}
}
例外:これはまさに私が受け取る例外です。
スレッド「Thread-2」での例外 java.util.LinkedList.getFirst(LinkedList.java:126) での java.util.NoSuchElementException java.util.LinkedList.element(LinkedList.java:476) での Consumer.removeListElement(Consumer. java:29) Consumer.run(Consumer.java:20) で