2013-10-02 28 views
1

我有一个并行执行两个线程的应用程序,每个执行一些动作,最终产生一个整数。在我的主线程中,我想对每个线程A和线程B产生的int执行一些操作(分别称它们为int a和int b),然后按照每个线程吐出它们的顺序输出它们。所以实际上,我每隔一段时间(例如每2秒)运行一个线程,每个线程都会吐出一个整数,我按照它们的顺序操作并打印出来。队列来收集线程的输出

为了做到这一点,我怎样才能将每条需要由gui线程打印的线索的整数汇总在一起?我可以使用主线程观察到的每个线程的队列,并且当它更新时,主GUI会操纵并输出它们?我怎么写这样的队列?

的代码为我的线程如下:

Timer timer = new Timer(); 
timer.scheduleAtFixedRate(new TimerTask() { 
    @Override 
    public void run() { 
     new Thread(new t1()).start(//TODO: pass in some parameter that this 
            //thread will write to); 
     new Thread(new t2()).start(); 
    } 
}, 0, period); 
+0

队列wait()和notify()。这些是你的关键字。现在没有时间详细说明,对不起。 – RaphMclee

回答

1

考虑这个解决方案,你可能会觉得它很有用。它使用ConcurrentLinkedQueue进行队列上的线程安全操作。

final Queue<Integer> queue1 = new ConcurrentLinkedQueue<Integer>(); 
final Queue<Integer> queue2 = new ConcurrentLinkedQueue<Integer>(); 

final Random r = new Random(); 

Timer timer = new Timer(); 
timer.scheduleAtFixedRate(new TimerTask() {    
    @Override 
    public void run() { 
     //Thread 1 
     new Thread(new Runnable() { 
      @Override 
      public void run() { 
       //even numbers 
       queue1.add(r.nextInt(50)*2); 
      } 
     }).start(); 

     //Thread 2 
     new Thread(new Runnable() { 
      @Override 
      public void run() { 
       //odd numbers 
       queue2.add(r.nextInt(50)*2 + 1); 
      } 
     }).start(); 
    } 
}, 0, 2000); 

//Main thread (maybe GUI) 
while (true){ 
    while (!queue1.isEmpty()){ 
     System.out.println("Thread-1: " + queue1.poll()); 
    } 
    while (!queue2.isEmpty()){ 
     System.out.println("Thread-2: " + queue2.poll()); 
    } 
} 

编辑

你真正需要的是一个生产者 - 消费者(见http://en.wikipedia.org/wiki/Producer%E2%80%93consumer_problem)。为了解决这个问题,我们将使用另一个队列ArrayBlockingQueue,因为这个数据结构让我们阻塞,直到产生(或消耗)为止。

final BlockingQueue<Integer> queue1 = new ArrayBlockingQueue<Integer>(1024); 
final BlockingQueue<Integer> queue2 = new ArrayBlockingQueue<Integer>(1024); 

final Random r = new Random();   

Timer timer = new Timer(); 
timer.scheduleAtFixedRate(new TimerTask() { 
    @Override 
    public void run() { 
     try { 
      //don't create threads here, this is already a thread, just produce the numbers 
      //If the queue is full `BlockingQueue.put()` will block until the consumer consume numbers. 

      //Producer even number 
      queue1.put(r.nextInt(50)*2); 

      //Producer odd number 
      queue2.put(r.nextInt(50)*2 + 1); 

     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
    } 
}, 0, 2000); 

//Now we create the threads that will take numbers from the producer. Don't worry about the `while (true)`, it is not wasting resources because `BlockingQueue.take()` will block the thread until something is produced. 

//Consumer 1 
new Thread(new Runnable() { 
    @Override 
    public void run() { 
     try { 
      while (true){ 
       System.out.println("Thread-1: " + queue1.take()); 

       //Or update some UI component 
      } 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
    } 
}).start(); 

//Consumer 2 
new Thread(new Runnable() { 
    @Override 
    public void run() { 
     try { 
      while (true){ 
       System.out.println("Thread-2: " + queue2.take()); 

       //Or update some UI component 
      } 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
    } 
}).start(); 
+0

问题是,定时器没有从run()中直接访问队列。该队列驻留在另一个类中。所以我可以通过它,当我加入run()时,其他类中的队列也会看到它被添加。换句话说,通过ref传递队列吗? –

+0

@JohnBaum访问队列是另一回事,你可以按你喜欢的方式去做。为了演示的目的,我使用了一个最终变量,但是你可以有一个单例,从一个对象中调用一个getter,等等。 – omainegra

+0

有一段时间(真)是检查新队列数据是否可用的唯一方法?有没有基于通知的系统,我可以使用,不阻止用户界面? –

1

尝试使用Executor开发框架,使用Callables代替的Runnable。使用Callable的优点之一是它提供了一种类似于Runnable run方法的call方法,但call方法可以为return一个值。所以在你的情况下,你可以从你的两个线程返回整数值,然后在主线程中使用它们。

0

将队列传递给两个线程的构造函数。

覆盖您传递的队列的offer/add方法,并添加您的逻辑来调用gui主线程,基本上在调用基类调用之后调用监听器。