线程并发问题java

时间:2016-02-18 10:49:04

标签: java multithreading

我正在运行两个线程类和第三个类(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();
    }
}

我面临的问题是:

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

  2. 永远不会打印部分生成的字符串。

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

  4. 我该如何解决这些问题?

4 个答案:

答案 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块,它应该有帮助。