繁体   English   中英

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

[英]Can I use one Runnable for Two threads such that one produces and one consumes?

在下面的代码中,我希望线程t1执行Runnable的产生,并让线程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();
    }
}

在下面的代码中,我希望线程t1执行Runnable的产生,并让线程t2执行Runnable的消耗。

第一个答案是您很可能不想这样做。 您应该有一个生产者类和一个消费者类。 如果他们需要共享数据,那就可以了,但是出于模块化目的,您应该将生产者代码和消费者代码分开。 例如,生产者和使用者代码可以共享一个BlockingQueue ,该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。

否。两个线程都将调用生产和消费。

您应该创建2个不同的可运行对象。 一种用于生产例程,另一种用于消耗例程。

有一个线程执行生产可运行,而一个线程执行消耗运行。

正确的方法是:

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()

如所写,两个线程都将进行两个函数调用。 在大多数情况下,最好将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。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM