Java 只有两个线程用于调用product和consume?
下面是关于运行生产者和消费者的线程的代码。Java 只有两个线程用于调用product和consume?,java,multithreading,producer-consumer,Java,Multithreading,Producer Consumer,下面是关于运行生产者和消费者的线程的代码。 public class PC1 { public static final int limit = 3; public static void main(String[] args) { List bag = new ArrayList(); Producer p = new Producer(bag); Consumer c = new Consumer(bag);
public class PC1 {
public static final int limit = 3;
public static void main(String[] args) {
List bag = new ArrayList();
Producer p = new Producer(bag);
Consumer c = new Consumer(bag);
Thread t1 = new Thread(p, "t1");
Thread t2 = new Thread(c, "t2");
Thread t3 = new Thread(p, "t3");
Thread t4 = new Thread(c, "t4");
Thread t5 = new Thread(p, "t5");
Thread t6 = new Thread(c, "t6");
t2.start();
t4.start();
t6.start();
t1.start();
t3.start();
t5.start();
}
}
class Producer implements Runnable {
private List bag;
public Producer(List bag) {
this.bag = bag;
}
@Override
public void run() {
synchronized (bag) {
while (true) {
while (bag.size() >= PC1.limit) {
bag.notify();
System.out.println(Thread.currentThread().getName() + "@@@@@@@@@@@");
try {
bag.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
int curr = bag.size();
bag.add(++curr);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " produce " + curr);
}
}
}
}
class Consumer implements Runnable {
private List bag;
public Consumer(List bag) {
this.bag = bag;
}
@Override
public void run() {
synchronized (bag) {
while (true) {
while (bag.size() <= 0) {
bag.notify();
System.out.println(Thread.currentThread().getName() + "!!!!!!!!!!!");
try {
bag.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
int curr = bag.size();
bag.remove(curr - 1);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " consume " + (bag.size() + 1));
}
}
}
}
公共类PC1{
公共静态最终整数限值=3;
公共静态void main(字符串[]args){
列表包=新的ArrayList();
生产者p=新生产者(袋);
消费者c=新消费者(袋);
螺纹t1=新螺纹(p,“t1”);
螺纹t2=新螺纹(c,“t2”);
螺纹t3=新螺纹(p,“t3”);
螺纹t4=新螺纹(c,“t4”);
螺纹t5=新螺纹(p,“t5”);
螺纹t6=新螺纹(c,“t6”);
t2.start();
t4.开始();
t6.开始();
t1.start();
t3.start();
t5.开始();
}
}
类生成器实现了Runnable{
私人名单袋;
公共制片人(名单袋){
这个袋子=袋子;
}
@凌驾
公开募捐{
同步(包){
while(true){
while(bag.size()>=PC1.limit){
bag.notify();
System.out.println(Thread.currentThread().getName()+“@@@@@@@@@”);
试一试{
等等;
}捕捉(中断异常e){
e、 printStackTrace();
}
}
int curr=袋大小();
加上(++货币);
试一试{
睡眠(100);
}捕捉(中断异常e){
e、 printStackTrace();
}
System.out.println(Thread.currentThread().getName()+“product”+curr);
}
}
}
}
类使用者实现Runnable{
私人名单袋;
公众消费者(列表袋){
这个袋子=袋子;
}
@凌驾
公开募捐{
同步(包){
while(true){
while(bag.size()Notify工作正常;即根据其指定方式。问题是Java不能保证对wait/Notify/notifyAll进行公平调度。这意味着某些线程可能比其他线程获得更多的工作
事实上,对于一个普通的程序来说,这并不重要:这根本不是问题。例如,在一个普通的多线程生产者/消费者应用程序中,哪个消费者线程处理生产者生产的东西并不重要。重要的是它们被高效地处理。实际上,这可能有性能优势在这种情况下,使用不公平的线程调度代替公平。一个原因是可以减少线程上下文切换的数量
那么你将如何实现你的目标呢
首先,不要使用wait/notify。如果您阅读这些方法的javadocs,您将看到没有公平性的保证
获得公平性的一种方法是使用ReentrantLock
实例化为fair==true
;有关详细信息,请参阅。通知工作正常;即根据其指定方式。“问题”Java不能保证对wait/notify/notifyAll的公平调度,这意味着一些线程可能比其他线程得到更多的工作
事实上,对于一个普通的程序来说,这并不重要:这根本不是问题。例如,在一个普通的多线程生产者/消费者应用程序中,哪个消费者线程处理生产者生产的东西并不重要。重要的是它们被高效地处理。实际上,这可能有性能优势在这种情况下,使用不公平的线程调度代替公平。一个原因是可以减少线程上下文切换的数量
那么你将如何实现你的目标呢
首先,不要使用wait/notify。如果您阅读这些方法的javadocs,您将看到没有公平性的保证
获得公平性的一种方法是使用实例化为fair==true
的ReentrantLock
;有关详细信息,请参阅。如果您将拥有多个生产者和一个消费者,则必须使用notifyAll()
;或者必须放弃wait()/notify()总之,切换到一个可重入锁定
,并使用两个条件
使用notify()的问题
当存在多个生产者或消费者时,在某些情况下,生产者可以唤醒另一生产者,消费者也可以唤醒另一消费者。一旦发生这种情况,循环就会中断,程序将无法再取得任何进展。有点像死锁:每个线程都在等待某个ot她想做点什么
该问题的奇特解决方案是使用单独的条件
变量:一个用于生产者唤醒消费者,另一个用于消费者唤醒生产者。解决该问题的钝器方法是使用notifyAll()
然后把所有人都叫醒。如果你要有不止一个生产者和一个消费者,那么你必须使用notifyAll()
;或者你必须完全放弃wait()/notify(),改为切换到ReentrantLock
,并使用两个条件
使用notify()的问题
当存在多个生产者或消费者时,在某些情况下,生产者可以唤醒另一生产者,消费者也可以唤醒另一消费者。一旦发生这种情况,循环就会中断,程序将无法再取得任何进展。有点像死锁:每个线程都在等待某个ot她想做点什么
这个问题的奇特解决方案是有单独的条件
变量:一个用于生产者唤醒消费者,另一个用于消费者唤醒生产者。解决这个问题的钝器方法是使用notifyAll()
,然后唤醒所有人。Stephen的答案