gpt4 book ai didi

java - 多线程 Java 应用程序中的问题 - 同步方法未按预期工作

转载 作者:行者123 更新时间:2023-11-30 04:59:05 24 4
gpt4 key购买 nike

我正在编写一个类似于java中的生产者-消费者的程序(但只有消费者部分,没有生产者线程)。尽管我正在调用同步方法的代码,但看起来关键区域正在由多个线程同时执行。

这是代码:

类Main.java:

package principal;

public class Main {

/**
* @param args
*/
public static void main(String[] args) {
final int tamanho_buffer=10;
final int quantidade_threads=10;

Pedido buffer[] = new Pedido[tamanho_buffer];
Consumidor consumidor[] = new Consumidor[quantidade_threads];

for (int i=0;i<tamanho_buffer;i++) {
buffer[i]=new Pedido();
}

for (int i=0;i<quantidade_threads;i++) {
consumidor[i]=new Consumidor();
}

for (int i=0;i<tamanho_buffer;i++) {
int identificador[]=new int[Pedido.getTamanho_identificador()];
identificador[0]=i;
buffer[i].setIdentificador(identificador);
buffer[i].setTexto("pacote de dados");
}

Consumidor.setBuffer(buffer);
Consumidor.setTamanho_buffer(tamanho_buffer);

for (int i=0;i<quantidade_threads;i++) {
consumidor[i].start();
}

for (int i=0;i<quantidade_threads;i++) {
try {
consumidor[i].join();
}catch(InterruptedException e ){
System.out.println("InterruptedException lancada");
}
}

System.out.println("Processamento encerrado.");

}

}

Pedido.java 类:

package principal;

public class Pedido {
private int identificador[];
private String texto;
static int tamanho_identificador=10;
int ti=tamanho_identificador;

public Pedido() {
this.identificador= new int[this.ti];
}

public static int getTamanho_identificador() {
return tamanho_identificador;
}

public int[] getIdentificador() {
return identificador;
}
public void setIdentificador(int[] identificador) {
this.identificador = identificador;
}
public String getTexto() {
return texto;
}
public void setTexto(String texto) {
this.texto = texto;
}

}

类Consumidor.java

package principal;

import java.util.Date;
import java.text.DateFormat;
import java.text.SimpleDateFormat;

public class Consumidor extends Thread {

private static Pedido buffer[];
private static int tamanho_buffer;
private static int posicao=0;

public static void setTamanho_buffer(int tamanhoBuffer) {
tamanho_buffer = tamanhoBuffer;
}

public static void setBuffer(Pedido[] buffer) {
Consumidor.buffer = buffer;
}

public void run() {
DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
while (posicao < Consumidor.tamanho_buffer ) {
// int identificador;
// identificador=buffer[posicao].getIdentificador()[0];;

Date datainicio = new Date();
String inicio=dateFormat.format(datainicio);

try {
Consumidor.sleep(1000);
} catch(InterruptedException e) {
System.out.println("InterruptedException lancada");
}

Date datafim = new Date();
String fim=dateFormat.format(datafim);

consomebuffer(inicio,fim);

}
}

synchronized void consomebuffer(String inicio, String fim) {
if (posicao < Consumidor.tamanho_buffer ) {
int identificador;
identificador=buffer[posicao].getIdentificador()[0];
System.out.println("Thread: "+Thread.currentThread()+" Pedido: "+identificador+" Inicio: "+inicio+" Fim: "+fim+" posicao "+posicao);
posicao++;
}
}
}

方法 consomebuffer 是同步的,但看起来变量 posicao(位置的葡萄牙语名称)正在被其他线程同时访问,这种情况不应该发生,因为它是同步方法。程序输出如下:

主题:主题[Thread-7,5,main] Pedido:0 起始:2011/09/24 21:14:18 结束:2011/09/24 21:14:19 posicao 0

主题:主题[Thread-6,5,main] Pedido:0 起始:2011/09/24 21:14:18 结束:2011/09/24 21:14:19 posicao 0

主题:主题[Thread-2,5,main] Pedido:0 起始:2011/09/24 21:14:18 结束:2011/09/24 21:14:19 posicao 0

主题:主题[Thread-9,5,main] Pedido:0 起始:2011/09/24 21:14:18 结束:2011/09/24 21:14:19 posicao 0

主题:主题[Thread-3,5,main] Pedido:4 起始:2011/09/24 21:14:18 结束:2011/09/24 21:14:19 posicao 4

主题:主题[Thread-5,5,main] 佩迪多:5 起始:2011/09/24 21:14:18 结束:2011/09/24 21:14:19 posicao 5

主题:主题[Thread-0,5,main] Pedido:0 起始:2011/09/24 21:14:18 结束:2011/09/24 21:14:19 posicao 5

主题:主题[Thread-8,5,main] Pedido:0 起始:2011/09/24 21:14:18 结束:2011/09/24 21:14:19 posicao 5

主题:主题[Thread-4,5,main] 佩迪多:5 起始:2011/09/24 21:14:18 结束:2011/09/24 21:14:19 posicao 5

主题:主题[Thread-1,5,main] Pedido:0 起始:2011/09/24 21:14:18 结束:2011/09/24 21:14:19 posicao 0

过程。

意识到位置值在不同线程之间重复出现。在输出中,posicao 在调用同步方法的每个线程中应该有不同的值。

最佳答案

每个 Thread 实例都在自身同步。为了使所有线程互斥,它们必须在一个公共(public)对象上同步。

也就是说,

public synchronized method(int parameter)
{
//do some stuff
}

的简写
public method(int parameter)
{
synchronized (this)
{
//do some stuff
}
}

如果您希望一堆线程彼此同步,您需要为它们提供一个可以同步的公共(public)对象。

例如,您可以在Consumidor.java的构造函数中添加

public Consumidator(Object monitor)
{
myMonitor = monitor
}

然后在运行中有

void consomebuffer(String inicio, String fim) {
synchronized (myMonitor)
{
if (posicao < Consumidor.tamanho_buffer ) {
int identificador;
identificador=buffer[posicao].getIdentificador()[0];
System.out.println("Thread: "+Thread.currentThread()+" Pedido: "+identificador+" Inicio: "+inicio+" Fim: "+fim+" posicao "+posicao);
posicao++;
}
}
}

然后,当您创建消费者数组时,向它们传递一个共享对象以进行同步。

关于java - 多线程 Java 应用程序中的问题 - 同步方法未按预期工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7542903/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com