Java 我不知道';根本无法获得线程同步
所以我读了很多关于Java中线程同步的书。我目前正在尝试有界缓冲区问题。当消费者继续消费产品时,生产者将继续在缓冲区中生产产品 如果缓冲区已满,生产商将等待,然后再生产另一种产品。 如果缓冲区为空,使用者将等待 然而,我的问题是,生产者只有在缓冲区为空时才开始生产,直到缓冲区满为止。消费者仅在缓冲区已满时开始消费,直到缓冲区为空为止 示例(缓冲区大小:5) 我希望这样,只要缓冲区未满,无论缓冲区是否为空,生产者都会生产。随后,我希望这样,只要缓冲区不是空的,无论缓冲区是否已满,消费者都会消费 我的代码怎么了Java 我不知道';根本无法获得线程同步,java,multithreading,synchronization,Java,Multithreading,Synchronization,所以我读了很多关于Java中线程同步的书。我目前正在尝试有界缓冲区问题。当消费者继续消费产品时,生产者将继续在缓冲区中生产产品 如果缓冲区已满,生产商将等待,然后再生产另一种产品。 如果缓冲区为空,使用者将等待 然而,我的问题是,生产者只有在缓冲区为空时才开始生产,直到缓冲区满为止。消费者仅在缓冲区已满时开始消费,直到缓冲区为空为止 示例(缓冲区大小:5) 我希望这样,只要缓冲区未满,无论缓冲区是否为空,生产者都会生产。随后,我希望这样,只要缓冲区不是空的,无论缓冲区是否已满,消费者都会消费 我
import java.util.LinkedList;
import java.util.Queue;
import java.util.Random;
import javax.swing.JOptionPane;
public class ProducerConsumer{
final static Queue<Product> buffer = new LinkedList<>();
private static int buffer_size, no_items, itemno = 1;
private static Random r = new Random();
public static void main(String[] args) {
try{
buffer_size = Integer.parseInt(JOptionPane.showInputDialog("Input Buffer size (default: 5)"));
if(buffer_size<0){
buffer_size = 5;
}
}catch(NumberFormatException nfe){
buffer_size = 5;
}
try{
no_items = Integer.parseInt(JOptionPane.showInputDialog("Input No. of Items (default: 10)"));
if(no_items<0){
no_items = 10;
}
}catch(NumberFormatException nfe){
no_items = 10;
}
Producer producer = new Producer();
Consumer consumer = new Consumer();
producer.start();
consumer.start();
}
static class Product {
private String name = "Product X";
private int productno;
public Product(int productno) {
this.productno = productno;
this.name = "Product "+productno;
}
public int number() {
return productno;
}
@Override
public String toString() {
return name;
}
}
static class Producer extends Thread{
public Producer(){
}
public void produce(){
Product p = new Product(itemno++);
try {
this.sleep(r.nextInt(100));
} catch (InterruptedException ex) {
Thread.interrupted();
}
buffer.add(p);
System.out.println("Produced "+p);
}
@Override
public void run(){
synchronized(buffer){
while(itemno<=no_items){
while(buffer.size()==buffer_size){
try{
buffer.wait(100);
}catch(InterruptedException e){
Thread.interrupted();
}
}
produce();
buffer.notifyAll();
}
}
}
}
static class Consumer extends Thread{
public Consumer(){
}
public boolean consume(){
try {
this.sleep(r.nextInt(100));
} catch (InterruptedException ex) {
Thread.interrupted();
}
Product product = buffer.remove();
System.out.println("Consumed "+product);
return product.number()==no_items;
}
@Override
public void run(){
synchronized(buffer){
boolean end = false;
while(!end){
while(buffer.isEmpty()){
try{
buffer.wait(100);
}catch(InterruptedException e){
Thread.interrupted();
}
}
end = consume();
buffer.notifyAll();
}
}
}
}
}
import java.util.LinkedList;
导入java.util.Queue;
导入java.util.Random;
导入javax.swing.JOptionPane;
公共类生产者消费者{
最终静态队列缓冲区=新LinkedList();
私有静态int缓冲区大小,无项,项号=1;
私有静态随机r=新随机();
公共静态void main(字符串[]args){
试一试{
buffer_size=Integer.parseInt(JOptionPane.showInputDialog(“输入缓冲区大小(默认值:5)”);
如果(buffer_size这是因为在退出synchronized
块之前,您已经获取了buffer
监视器并生成了N次,所有这些都在while循环内
尝试将while
放在synchronized
块之外,这样就可以让另一个线程在并发生产/消费期间获得锁
请注意,notifyAll
实际上不会影响其他线程,直到通知线程退出synchronized
区域
编辑:我在做了建议的更改后运行了它,得到了以下输出
Produced Product 1
Produced Product 2
Produced Product 3
Consumed Product 1
Consumed Product 2
Consumed Product 3
Produced Product 4
Produced Product 5
Consumed Product 4
Consumed Product 5
Produced Product 6
Consumed Product 6
Produced Product 7
Produced Product 8
Produced Product 9
Produced Product 10
Consumed Product 7
Consumed Product 8
Consumed Product 9
Consumed Product 10
这是因为在退出synchronized
块之前,您已经获取了缓冲区
监视器并生成了N次,所有这些都在while循环中
尝试将while
放在synchronized
块之外,这样就可以让另一个线程在并发生产/消费期间获得锁
请注意,notifyAll
实际上不会影响其他线程,直到通知线程退出synchronized
区域
编辑:我在做了建议的更改后运行了它,得到了以下输出
Produced Product 1
Produced Product 2
Produced Product 3
Consumed Product 1
Consumed Product 2
Consumed Product 3
Produced Product 4
Produced Product 5
Consumed Product 4
Consumed Product 5
Produced Product 6
Consumed Product 6
Produced Product 7
Produced Product 8
Produced Product 9
Produced Product 10
Consumed Product 7
Consumed Product 8
Consumed Product 9
Consumed Product 10
由于两个线程在缓冲区上都是同步的,因此在任何时候都只有一个线程在运行。一个线程向另一个线程发出恢复运行的信号,并在调用buffer.wait()时挂起自身。包含buffer.wait()的while循环中的逻辑调用,(buffer.size()==buffer\u size)和(buffer.isEmpty()),只允许循环在其功能(生产者或消费者)已完成且无法继续时运行
程序的执行方式如下:Producer将生成5项,然后while循环条件将为true,它将调用buffer.wait()以允许consumer运行。consumer将开始运行并使用,直到buffer为空,在这种情况下while条件将为true,它将调用buffer.wait()并允许Producer再次运行
要允许两个线程同时运行(这可能是您真正想要的),您应该仅在需要安全访问缓冲区时调用synchronize(buffer)。一种方法是使用以下代码块:
static class Producer extends Thread {
public Producer() {
}
public void produce() {
Product p = new Product(itemno++);
try {
this.sleep(r.nextInt(100));
} catch (InterruptedException ex) {
Thread.interrupted();
}
synchronized(buffer) {
buffer.add(p);
}
System.out.println("Produced " + p);
}
@Override
public void run() {
while (itemno <= no_items) {
while (buffer.size() == buffer_size) {
try {
sleep(100);
} catch (InterruptedException e) {
Thread.interrupted();
}
}
produce();
}
}
}
static class Consumer extends Thread {
public Consumer() {
}
public boolean consume() {
try {
this.sleep(r.nextInt(100));
} catch (InterruptedException ex) {
Thread.interrupted();
}
Product product;
synchronized (buffer) {
product = buffer.remove();
}
System.out.println("Consumed " + product);
return product.number() == no_items;
}
@Override
public void run() {
boolean end = false;
while (!end) {
while (buffer.isEmpty()) {
try {
sleep(100);
} catch (InterruptedException ex) {
Logger.getLogger(TrashMe.class.getName()).log(Level.SEVERE, null, ex);
}
}
end = consume();
}
}
}
静态类生成器扩展线程{
公共制片人(){
}
公共产品{
产品p=新产品(itemno++);
试一试{
睡眠(r.nextInt(100));
}捕获(中断异常例外){
Thread.interrupted();
}
已同步(缓冲区){
添加(p);
}
系统输出打印项次(“生产”+p);
}
@凌驾
公开募捐{
while(itemno由于两个线程都在缓冲区上同步,因此在任何时候都只有一个线程在运行。一个线程向另一个线程发出信号,要求其恢复运行,并在调用buffer.wait()时挂起自身。包含buffer.wait()的while循环中的逻辑调用,(buffer.size()=buffer\u size)和(buffer.isEmpty()),只允许循环在其功能(生产者或消费者)已完成且无法继续时运行
程序的执行方式如下:Producer将生成5项,然后while循环条件将为true,它将调用buffer.wait()以允许consumer运行。consumer将开始运行并使用,直到buffer为空,在这种情况下while条件将为true,它将调用buffer.wait()并允许Producer再次运行
要允许两个线程同时运行(这可能是您真正想要的),您应该仅在需要安全访问缓冲区时调用synchronize(buffer)。一种方法是使用以下代码块:
static class Producer extends Thread {
public Producer() {
}
public void produce() {
Product p = new Product(itemno++);
try {
this.sleep(r.nextInt(100));
} catch (InterruptedException ex) {
Thread.interrupted();
}
synchronized(buffer) {
buffer.add(p);
}
System.out.println("Produced " + p);
}
@Override
public void run() {
while (itemno <= no_items) {
while (buffer.size() == buffer_size) {
try {
sleep(100);
} catch (InterruptedException e) {
Thread.interrupted();
}
}
produce();
}
}
}
static class Consumer extends Thread {
public Consumer() {
}
public boolean consume() {
try {
this.sleep(r.nextInt(100));
} catch (InterruptedException ex) {
Thread.interrupted();
}
Product product;
synchronized (buffer) {
product = buffer.remove();
}
System.out.println("Consumed " + product);
return product.number() == no_items;
}
@Override
public void run() {
boolean end = false;
while (!end) {
while (buffer.isEmpty()) {
try {
sleep(100);
} catch (InterruptedException ex) {
Logger.getLogger(TrashMe.class.getName()).log(Level.SEVERE, null, ex);
}
}
end = consume();
}
}
}
静态类生成器扩展线程{
公共制片人(){
}
公共产品{
产品p=新产品(itemno++);
试一试{
睡眠(r.nextInt(100));
}捕获(中断异常例外){
Thread.interrupted();
}
已同步(缓冲区){
添加(p);
}
系统输出打印项次(“生产”+p);
}
@凌驾
公开募捐{
while(itemno)也是一个旁注。你应该使用Thread.sleep(millis)
而不是这个。sleep(millis)
sleep
是一个静态方法,总是在Thread.currentThread()上执行
这反过来会对你有用,因为你正以这种方式使用它,但它可能会在将来烧死你。另外,顺便说一句,你应该