线程并发问题 java



我正在运行两个线程类和一个第三个类(执行)它们。

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();
    }
}

我面临的问题是这些:

  1. 一些生成的字符串被打印了不止一次,这意味着一旦有一些字符串被推入q,多个线程会同时删除该元素并打印。

  2. 某些生成的字符串永远不会打印。

  3. 有时,输出会延迟,即如果 Class1 生成 5 个字符串,则只打印 3 个字符串。现在,如果它再生成 3 个字符串,则打印前 2 个(左)字符串。

我该如何解决这些问题?

要么使用线程安全的Queuejava.util.concurrent实现(例如 BlockingQueue ) 或使用synchronized关键字。

另请参阅 https://docs.oracle.com/javase/tutorial/essential/concurrency/sync.html

LinkedList不是线程安全的。你应该使用某种BlockingQueue

    public static BlockingQueue<String> q = new ArrayBlockingQueue<String>(20);
一些生成的字符串被打印

了不止一次,这意味着一旦有一些字符串被推入 q,多个线程就会同时删除该元素并打印。

这很可能是由于对q的访问未同步,即Class2调用的两个或多个实例几乎同时remove()弄乱了也不安全的LinkedList实现。

您可能想要的是循环内的synchronized(Execute.q){ ... }块(不包括睡眠和收益调用)。

某些生成的字符串永远不会打印。

这可能与上述原因相同,因为您在同时呼叫remove()等时会弄乱LinkedList

有时,输出会延迟,即如果 Class1 生成 5 个字符串,则只打印 3 个字符串。现在,如果它再生成 3 个字符串,则打印前 2 个(左)字符串。

线程不保证以任何顺序运行,因此生产者可以运行 5 次,然后选择使用者运行 3 次。这里没有什么不寻常的。

尝试使用 public static volatile Queue<String> q = new LinkedList<String>();而不是 public static Queue<String> q = new LinkedList<String>();

它应该在不同步方法或使用同步块的情况下有所帮助。

最新更新