我正在尝试使用 ReentrantLock
实现消费者-生产者,如下所示:
class Producer implements Runnable {
private List<String> data;
private ReentrantLock lock;
Producer(List<String> data,ReentrantLock lock)
{
this.data = data;
this.lock = lock;
}
@Override
public void run() {
int counter = 0;
synchronized (lock)
{
while (true)
{
if ( data.size() < 5)
{
counter++;
data.add("writing:: "+counter);
}
else
{
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
}
class Consumer implements Runnable{
private List<String> data;
private ReentrantLock lock;
Consumer(List<String> data,ReentrantLock lock)
{
this.data = data;
this.lock = lock;
}
@Override
public void run() {
int counter = 0;
synchronized (lock)
{
while (true)
{
if ( data.size() > 0)
{
System.out.println("reading:: "+data.get(data.size()-1));
data.remove(data.size()-1);
}
else
{
System.out.println("Notifying..");
lock.notify();
}
}
}
}
}
public class ProducerConsumer {
public static void main(String[] args) {
List<String> str = new LinkedList<>();
ReentrantLock lock= new ReentrantLock();
Thread t1 = new Thread(new Producer(str,lock));
Thread t2 = new Thread(new Consumer(str,lock));
t1.start();
t2.start();
}
}
因此,它只向列表写入一次,然后消费者无限期地等待。为什么会这样?为什么 Producer 不获取锁?
最佳答案
@Antoniosss 是对的。您没有正确使用 ReentrantLock,而是可以将其替换为对象。如果你想改用 ReentrantLock(这是最新的),那么我建议如下:
package Multithreading;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
class Producer implements Runnable{
private List<String> data;
private ReentrantLock lock;
Producer(List<String> data,ReentrantLock lock)
{
this.data = data;
this.lock = lock;
}
@Override
public void run() {
int counter = 0;
while (true)
{
try {
lock.lock();
if ( data.size() < 5)
{
counter++;
data.add("writing:: " + counter);
}
}finally {
lock.unlock();
}
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class Consumer implements Runnable{
private List<String> data;
private ReentrantLock lock;
Consumer(List<String> data,ReentrantLock lock)
{
this.data = data;
this.lock = lock;
}
@Override
public void run() {
int counter = 0;
while (true)
{
try {
lock.lock();
if ( data.size() > 0)
{
System.out.println("reading:: "+data.get(data.size()-1));
data.remove(data.size()-1);
}
}finally {
lock.unlock();
}
try
{
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
public class ProducerConsumer {
public static void main(String[] args) {
List<String> str = new LinkedList<>();
ReentrantLock lock= new ReentrantLock();
Thread t1 = new Thread(new Producer(str,lock));
Thread t2 = new Thread(new Consumer(str,lock));
t1.start();
t2.start();
}
}
我删除了通知调用,但如果你真的需要一次让一个线程进入,只需使用 lock.notify()
关于java - 使用重入锁的生产者消费者不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51197639/