2014-06-06 62 views
2

我明白同步的概念,但我现在肯定为什么是实现这种方式,所以我需要在这里一点点的帮助:同步队列在多线程

我有2个线程:

PeriodicalThread将定期接收数据(假设每5秒),并把它放在一个Queue(使用ArrayDeque的时刻,但我不知道是否有任何其他Queue实施,将更好地工作)

ProccessThread将不断检查Queue看看它是否为空。如果它不是空的,它将处理数据(FIFO)

所以,在我第一次实现将是:

// Both threads are inner class so they have access to Queue 

private Queue queue; 
private boolean isReadyToProccess; 


class PeriodicalThread extends Thread { 
    public void run() { 
     while(true) { 
      if(isNewDataAvailable) { 
       // create Data object 
       queue.add(data); 
      } 
     } 
    } 
} 

class ProcessThread extends Thread { 
    public void run() { 
     while(true) { 
      if(!queue.isEmpty() && isReadyToProccess) { 
       Data data = queue.poll(); 
       processData(data); 
      } 
     } 
    } 
} 

private void processData(Data data) { 
    // this method send data over network, and the server response callback 
    // changes isReadyToProcess value to true. 
} 

然后想处理同步,我不知道我是否应该使用lock对象时(以及它是如何实现的),或者如果已经有一个包Queue实现,它是线程安全的(因为add()poll()方法)

编辑:我忘记了标志isReadyToProcess指示下一个队列Data对象是...好,准备好被处理。这个标志也应该同步。

+1

查找到'BlockingQueue'。 –

+0

布尔标志如何告诉你有关队列中下一个对象的内容?如果队列中有很多对象呢? –

回答

2

ArrayDeque不支持并发。相反,请使用支持并发工作的真实队列,如BlockingQueue及其在java.util.concurrent包中的其中一个实现。我建议使用LinkedBlockingQueue

如果您需要在您的线程之间共享标志,最好使用AtomicBoolean而不是手动同步原始字段boolean

注意:如果您要使用并发进程,最好使用java.util.concurrent软件包提供的类,该软件包已支持开箱即用的锁定和同步。

1

您正在寻找Blocking Queue实施

这提供的功能哪些你正在寻找框。这就是为什么它最适合生产者消费者的例子。

下面是一个例子

public class BlockingQueueExample { 

    public static void main(String[] args) throws Exception { 

     BlockingQueue queue = new ArrayBlockingQueue(1024); 

     Producer producer = new Producer(queue); 
     Consumer consumer = new Consumer(queue); 

     new Thread(producer).start(); 
     new Thread(consumer).start(); 

     Thread.sleep(4000); 
    } 
} 


public class Producer implements Runnable{ 

    protected BlockingQueue queue = null; 

    public Producer(BlockingQueue queue) { 
     this.queue = queue; 
    } 

    public void run() { 
     try { 
      queue.put("1"); 
      Thread.sleep(1000); 
      queue.put("2"); 
      Thread.sleep(1000); 
      queue.put("3"); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
    } 
} 


public class Consumer implements Runnable{ 

    protected BlockingQueue queue = null; 

    public Consumer(BlockingQueue queue) { 
     this.queue = queue; 
    } 

    public void run() { 
     try { 
      System.out.println(queue.take()); 
      System.out.println(queue.take()); 
      System.out.println(queue.take()); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
    } 
} 
+0

不要使用原始'BlockingQueue'。 –

+0

@LuiggiMendoza,我不知道_raw_ BlockingQueue是什么,但上面的例子使用了一个ArrayBlockingQueue。 –

+0

@jameslarge [Java教程。原始类型](http://docs.oracle.com/javase/tutorial/java/generics/rawTypes.html) –

0

您可以使用Java阻塞队列或Collections.synchronizedList(新的LinkedList <>()),我喜欢Collections.synchronized ......因为它是有效的使你的集合线程安全,并且你不打扰锁和标志和类似的东西......只是编写逻辑可读代码。

的LinkedList将为您提供addfirst仅()addlast仅()和ofcourse getFirst(),getLast()来实现FIFO或后进先出法的行为...