我可以使用一个Runnable用于两个线程,一个生产,一个消耗?

时间:2013-06-24 20:32:36

标签: java multithreading producer-consumer

在下面的代码中,我希望Thread t1执行Runnable和Thread t2的生成以执行Runnable的消耗。这会有用吗?

class Processor implements Runnable {
    @override
    run(){
        produce();
        consume();
    }
    void produce(){
        // code to produce, synchronize
    }
    void consume(){
        // code to consume, synchronize
    }
}

Class App {
    public static void main(String[] args){
        Processor p = new Processor()
        Thread t1 = new Thread(p);
        t1.start();
        Thread t2 = new Thread(p); 
        t2.start();
    }
}

4 个答案:

答案 0 :(得分:3)

  

在下面的代码中,我希望Thread t1执行Runnable和Thread t2的生成以执行Runnable的消耗。

第一个答案是,你很可能不想这样做。你应该有一个生产者类和一个消费者类。如果他们需要共享数据然后很好,但您应该将生产者和消费者代码分开以实现模块化目的。例如,生产者和消费者代码可以共享一个BlockingQueue,它将被传递到两个类中并用于交换工作。

由于您的代码目前已编写,因此每个线程显然只会调用produce()然后调用consume()。我假设代码是作为一个例子编写的。

如果你真的想在同一个类中组合生产者和消费者代码,你可以传递某种布尔值或其他选择器来告诉线程生成或消费。

例如:

 public class ProducerConsumerRunnable implements Runnable {
      private final Processor processor;
      private final boolean consume;
      public ProducerConsumerRunnable(Processor processor, boolean consume) {
          this.processor = processor;
          this.consume = consume;
      }
      public void run() {
          if (consume) {
              processor.consume()
          } else {
              processor.produce()
          }
      }
 }

那么你就可以开始你的主题:

Processor p = new Processor()
Thread producerThread = new Thread(new ProducerConsumerRunnable(p, false));
producerThread.start();
Thread consumerThread = new Thread(new ProducerConsumerRunnable(p, true));
consumerThread.start();

修改

当您应该致电thread.run()时,您的代码正在调用thread.start()。调用run()只会在前台线程中运行runnable,而start()实际上会在后台调用一个线程然后调用run。

答案 1 :(得分:0)

没有。两个线程都会调用产生和消费。

您应该创建2个不同的runnable。一个用于生产例程,一个用于消耗例程。

让一个线程执行produce runnable,一个线程执行consume runnable。

答案 2 :(得分:0)

正确的方法:

class App {
    public static void main(String[] args){
        Thread t1 = new Thread(){
            @Override run(){
                //insert produce method here
            }
        }
        Thread t2 = new Thread(){
            @Override run(){
                //insert consume method here
            }
        }
        t1.start(); // NOT run()!
        t2.start();
    }
}

这样,两个线程之间需要的任何共享变量都可以添加到App类中。

另外,正如我在代码中指出的那样,您使用Thread.start()来启动新主题,而不是Thread.run()

答案 3 :(得分:0)

如上所述,两个线程都会进行两个函数调用。像这样的大多数情况,你可能最好将produce()和consume()函数放在不同的类中;如果还有很多其他的共享逻辑,那么使用继承来使它们成为一些公共基类的子类(如果需要可能是抽象的),它实现了共享逻辑。

如果他们绝对,肯定必须是同一个类(他们可能不会),你可以尝试在Processor类中添加一个布尔值,类似于

class Processor implements Runnable
{
public Boolean producer;
@override
run()
{
if(producer){
    produce();
}
else{
    consume();
}
}
void produce()
{
// code to produce, synchronize
}
void consume()
{
// code to consume, synchronize
}
}

并将producer设置为false,另一个设置为true,然后再运行它们。