队列从线程收集输出

时间:2013-10-02 04:49:05

标签: java multithreading

我有一个并行执行两个线程的应用程序,每个线程执行一些操作,最终导致产生一个整数。在我的主线程中,我想对每个线程A和线程B(分别调用它们分别为int a和int b)生成的int执行一些操作,然后按照每个线程将它们吐出的顺序输出它们。所以从本质上讲,我定期运行每个线程(比如说每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);

3 个答案:

答案 0 :(得分:1)

尝试使用Executor框架,该框架使用Callables而不是Runnables。使用Callable的一个优点是它提供了类似于Runnable call方法的run方法,但call方法可以return一个值。因此,在您的情况下,您可以从两个线程返回整数值,然后可以在主线程中使用它们。

答案 1 :(得分: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();

答案 2 :(得分:0)

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

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