![](/img/trans.png)
[英]How do I use wait() and notify() if I have one Runnable and one that implements Threads?
[英]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.