你的代码没有问题,我重新组织了一下,以便更好地观察结果。import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;/**
* 多线程生产者-消费者示例
*/
public class Basket { public static final int BASKET_CAPACITY = 5; private List<String> list = new ArrayList<>(); private Lock lock = new ReentrantLock(); private Condition setter = lock.newCondition(); //篮子为满的条件 private Condition getter = lock.newCondition(); //篮子为空的条件 // 放入苹果
public void addApple() throws InterruptedException {
try {
lock.lock();
while (list.size() >= BASKET_CAPACITY) {
outputThreadMessage("篮子已满,等待取出", false);
setter.await();
}
list.add("红富士");
outputThreadMessage("放入苹果: 篮子里还有" + list.size(), false); getter.signalAll();
} finally {
lock.unlock();
}
} // 取出苹果
public void removeApple() throws InterruptedException {
try {
lock.lock();
while (list.size() <= 0) {
outputThreadMessage("篮子已空,等待放入", true);
getter.await();
}
list.remove(0);
outputThreadMessage("取出苹果: 篮子里还有" + list.size(), true); setter.signalAll();
} finally {
lock.unlock();
}
} public static void main(String[] args) {
final Basket baskert = new Basket(); // 通过调整 AddAppleTask 和 RemoveAppleTask 的线程数,可以
// 观察篮子满或空的情况
new Thread(new AddAppleTask(baskert)).start();
new Thread(new AddAppleTask(baskert)).start(); new Thread(new RemoveAppleTask(baskert)).start();
new Thread(new RemoveAppleTask(baskert)).start();
} /**
* 放入苹果线程
*/
private static class AddAppleTask implements Runnable { private final Basket basket; public AddAppleTask(Basket basket) {
this.basket = basket;
} public void run() {
try {
while (waitRandomTime()) {
basket.addApple();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
} } /**
* 取出苹果线程
*/
private static class RemoveAppleTask implements Runnable { private final Basket basket; public RemoveAppleTask(Basket basket) {
this.basket = basket;
} public void run() {
try {
while (waitRandomTime()) {
basket.removeApple();
}
} catch (InterruptedException e) {
e.printStackTrace();
} } } ///////////////////////////////////////////////////////// public static final Random RANDOM = new Random(); private static void outputThreadMessage(String message, boolean err) {
if (err) {
System.err.printf("[%10s] %s\n", Thread.currentThread().getName(), message);
} else {
System.out.printf("[%10s] %s\n", Thread.currentThread().getName(), message);
}
} private static boolean waitRandomTime() {
try {
Thread.sleep(RANDOM.nextInt(1000) + 500);
return true;
} catch (InterruptedException e) {
e.printStackTrace();
return false;
}
}
}
import java.util.List;
import java.util.Random;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;/**
* 多线程生产者-消费者示例
*/
public class Basket { public static final int BASKET_CAPACITY = 5; private List<String> list = new ArrayList<>(); private Lock lock = new ReentrantLock(); private Condition setter = lock.newCondition(); //篮子为满的条件 private Condition getter = lock.newCondition(); //篮子为空的条件 // 放入苹果
public void addApple() throws InterruptedException {
try {
lock.lock();
while (list.size() >= BASKET_CAPACITY) {
outputThreadMessage("篮子已满,等待取出", false);
setter.await();
}
list.add("红富士");
outputThreadMessage("放入苹果: 篮子里还有" + list.size(), false); getter.signalAll();
} finally {
lock.unlock();
}
} // 取出苹果
public void removeApple() throws InterruptedException {
try {
lock.lock();
while (list.size() <= 0) {
outputThreadMessage("篮子已空,等待放入", true);
getter.await();
}
list.remove(0);
outputThreadMessage("取出苹果: 篮子里还有" + list.size(), true); setter.signalAll();
} finally {
lock.unlock();
}
} public static void main(String[] args) {
final Basket baskert = new Basket(); // 通过调整 AddAppleTask 和 RemoveAppleTask 的线程数,可以
// 观察篮子满或空的情况
new Thread(new AddAppleTask(baskert)).start();
new Thread(new AddAppleTask(baskert)).start(); new Thread(new RemoveAppleTask(baskert)).start();
new Thread(new RemoveAppleTask(baskert)).start();
} /**
* 放入苹果线程
*/
private static class AddAppleTask implements Runnable { private final Basket basket; public AddAppleTask(Basket basket) {
this.basket = basket;
} public void run() {
try {
while (waitRandomTime()) {
basket.addApple();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
} } /**
* 取出苹果线程
*/
private static class RemoveAppleTask implements Runnable { private final Basket basket; public RemoveAppleTask(Basket basket) {
this.basket = basket;
} public void run() {
try {
while (waitRandomTime()) {
basket.removeApple();
}
} catch (InterruptedException e) {
e.printStackTrace();
} } } ///////////////////////////////////////////////////////// public static final Random RANDOM = new Random(); private static void outputThreadMessage(String message, boolean err) {
if (err) {
System.err.printf("[%10s] %s\n", Thread.currentThread().getName(), message);
} else {
System.out.printf("[%10s] %s\n", Thread.currentThread().getName(), message);
}
} private static boolean waitRandomTime() {
try {
Thread.sleep(RANDOM.nextInt(1000) + 500);
return true;
} catch (InterruptedException e) {
e.printStackTrace();
return false;
}
}
}
import java.util.Collections;
import java.util.List;
import java.util.Random;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;/**
* 多线程生产者-消费者示例
*/
public class Basket { public static final int BASKET_CAPACITY = 5; private List<String> list = new ArrayList<>(); private Lock lock = new ReentrantLock(); private Condition setter = lock.newCondition(); //篮子为满的条件 private Condition getter = lock.newCondition(); //篮子为空的条件 // 放入苹果
public void addApple() throws InterruptedException {
try {
lock.lock();
while (list.size() >= BASKET_CAPACITY) {
addMessage("+++ 篮子已满,等待取出");
setter.await();
}
list.add("红富士");
addMessage("+++ 放入苹果: 篮子里还有" + list.size()); getter.signalAll();
} finally {
lock.unlock();
}
} // 取出苹果
public void removeApple() throws InterruptedException {
try {
lock.lock();
while (list.size() <= 0) {
addMessage("--- 篮子已空,等待放入");
getter.await();
}
list.remove(0);
addMessage("--- 取出苹果: 篮子里还有" + list.size()); setter.signalAll();
} finally {
lock.unlock();
}
} ///////////////////////////////////////////////////////// public static void main(String[] args) throws Exception {
final Basket baskert = new Basket(); // 通过调整 AddAppleTask 和 RemoveAppleTask 的线程数,可以
// 观察篮子满或空的情况 startTask(new AddAppleTask(baskert));
startTask(new AddAppleTask(baskert));
startTask(new AddAppleTask(baskert)); startTask(new RemoveAppleTask(baskert));
startTask(new RemoveAppleTask(baskert)); System.out.println("线程运行中,请等待 10 秒..."); Thread.sleep(10000); // 让线程运行 10 秒钟
stop = true;
Thread.sleep(2000); // 等待所有线程停止 outputMessagesWithOrder(); // 按照次序打印消息
} private static void startTask(Runnable runnable) {
Thread thread = new Thread(runnable);
thread.setDaemon(true);
thread.start();
} ///////////////////////////////////////////////////////// /**
* 放入苹果线程
*/
private static class AddAppleTask implements Runnable { private final Basket basket; public AddAppleTask(Basket basket) {
this.basket = basket;
} public void run() {
try {
while (waitRandomTime()) {
basket.addApple();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
} } /**
* 取出苹果线程
*/
private static class RemoveAppleTask implements Runnable { private final Basket basket; public RemoveAppleTask(Basket basket) {
this.basket = basket;
} public void run() {
try {
while (waitRandomTime()) {
basket.removeApple();
}
} catch (InterruptedException e) {
e.printStackTrace();
} } } ///////////////////////////////////////////////////////// public static final Random RANDOM = new Random(); private static boolean stop = false; private static List<String> messages = new ArrayList<>(); private static final AtomicInteger serial = new AtomicInteger(); private static synchronized void addMessage(String message) {
messages.add(String.format("%4d[%8s] %s",
serial.incrementAndGet(), Thread.currentThread().getName(), message));
} private static void outputMessagesWithOrder() {
Collections.sort(messages); for (String message : messages) {
System.out.println(message);
}
} private static boolean waitRandomTime() {
try {
Thread.sleep(RANDOM.nextInt(1000) + 500);
} catch (InterruptedException e) {
e.printStackTrace();
}
return !stop;
}
}
不过你的输出结果和预期相同,是不是因为你waitRandomTime方法调用了sleep。为什么不用sleep执行顺序就不对,巧合吗
数量 50 100,500 结果都一样
你代码耗时太低了,应该是计算线程优先级的问题,我这里调到30就能出现你想要的结果,加上Thread.sleep(1000)调到20就能出现你要的结果。