我正在运行两个线程类和第三个类(Execute)。
Class1 extends Thread{
public void run(){
while(!Thread.currentThread().isInterrupted()){
Thread.sleep(random());
//random will ensure non-periodicity in generating strings
//Because of this, sometimes, many strings are generated simultaneously and other times, there is delay.
Execute.q.add(generateRandomString());
}
}
}
Class2 extends Thread{
public void run(){
while(!Thread.currentThread().isInterrupted()){
Thread.yield();
if(!Execute.q.isEmpty){
System.out.println(Execute.q.remove());
}
}
}
}
public class Execute{
public static Queue<String> q = new LinkedList<String>();
public static void main(String args[]){
(new Class1()).start();
(new Class1()).start();
(new Class2()).start();
(new Class2()).start();
}
}
我面临的问题是:
一些生成的字符串被多次打印,这意味着只要有一些字符串被推入q
,就会有多个线程同时删除该元素,并打印
永远不会打印部分生成的字符串。
有时,输出会延迟,即。如果Class1生成了5个字符串,则只打印3个字符串。现在,如果它再生成3个字符串,则会打印前2个(左)。
我该如何解决这些问题?
答案 0 :(得分:2)
使用Queue
中的线程安全java.util.concurrent
实施(例如BlockingQueue
)或使用synchronized
关键字。
另见https://docs.oracle.com/javase/tutorial/essential/concurrency/sync.html
答案 1 :(得分:1)
LinkedList
不是线程安全的。你应该使用某种BlockingQueue
:
public static BlockingQueue<String> q = new ArrayBlockingQueue<String>(20);
答案 2 :(得分:1)
一些生成的字符串被多次打印,这意味着只要有一些字符串被推入q,多个线程会同时删除该元素并打印。
这很可能是由于访问q
未被同步,即两个或多个Class2
调用remove()
实例几乎同时弄乱了LinkedList
实施也不是线程安全的。
你可能想要的是循环中的synchronized(Execute.q){ ... }
块(不包括sleep和yield调用)。
永远不会打印某些生成的字符串。
这可能与上述原因相同,因为您在同时调用LinkedList
等时弄乱了remove()
。
有时,输出会延迟,即。如果Class1生成了5个字符串,则只打印3个字符串。现在,再次如果它再生成3个字符串,则前面的2个(左)打印出来。
不保证线程以任何顺序运行,因此生产者可以运行5次,然后选择使用者运行3次。这里没什么不寻常的。
答案 3 :(得分:0)
尝试使用
public static volatile Queue<String> q = new LinkedList<String>();
代替
public static Queue<String> q = new LinkedList<String>();
如果没有同步方法或使用synchronized块,它应该有帮助。