2011-09-25 6 views
1

저는 프로듀서 - 소비자와 유사하지만 (프로듀서 스레드가없는 소비자 전용 부분을 가진) java의 프로그램을 코딩하고 있습니다. 동기화 된 메서드의 코드를 호출한다는 사실에도 불구하고 여러 영역에서 동시에 중요한 영역을 실행하는 것처럼 보입니다.멀티 스레드 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는 syn이다. chronized하지만 변수 posicao (위치에 대한 포르투갈어 이름)가 동시에 발생하지 않아야하는 다른 스레드에 의해 액세스되고있는 것처럼 보입니다.이 방법은 동기화 된 방법입니다. 프로그램 출력은 다음과 같습니다 :

글타래 (쓰레드) : Thread [Thread-7,5, main] Pedido : 0 Inicio : 2011/09/24 21:14:18 Fim : 2011/09/24 21:14 : 19 posicao 0

스레드 : 스레드 [6,5 스레드 메인] Pedido : 0 크리에이터 : 2011/09/24 21시 14분 18초 FIM : 2011/09/24 21시 14분 19초 posicao 0

스레드 : 스레드 [실 -2,5- 메인] Pedido : 0 크리에이터 : 2011/09/24 21시 14분 18초 FIM : 2011/09/24 21시 14분 19초 posicao 0

스레드 : 스레드 [Thread-9,5, main] Pedido : 0 Inicio : 2011/09/24 21:14:18 Fim : 2011/09/24 21:14:19 posicao 0

,

스레드 : 스레드 [스레드 3,5- 메인] Pedido 4 크리에이터 : 2011/09/24 21시 14분 18초 FIM : 2011/09/24 21시 14분 19초 posicao 4

스레드 : 주제 [Thread-5,5, main] Pedido : 5 정보 : 2011/09/24 21:14:18 Fim : 2011/09/24 21:14:19 posicao 5

글타래 (쓰레드 0) , 5, main] Pedido : 0 Inicio : 2011/09/24 21:14:18 Fim : 2011/09/24 21:14:19 posicao 5

실 : Thread [스레드 -8,5, 메인] Pedido : 0 Inicio : 2011/09/24 21:14:18 Fim : 2011/09/24 21:14:19 posicao 5

실 : 스레드 [Thre ad-4,5, main] Pedido : 5 Inicio : 2011/09/24 21:14:18 Fim : 2011/09/24 21:14:19 posicao 5

스레드 : 스레드 [스레드 -1 , 메인] Pedido : 0 증상 : 2011/09/24 21:14:18 Fim : 2011/09/24 21:14:19 posicao 0

Processamento encerrado.

위치 값이 다른 스레드간에 반복되는 것처럼 보입니다. 출력에서 posicao는 synchronized 메소드를 호출하는 각 스레드에서 다른 값을 가져야합니다.

답변

2

각 스레드 인스턴스가 자체적으로 동기화됩니다. 모든 스레드를 상호 배타적으로 만들려면 공통 객체에서 동기화해야합니다.일반적인 객체가 동기화는 서로 동기화 스레드의 무리를 원하는 경우입니다

,

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

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

속기, 당신은 그들에게 제공해야 .

예를 들어, 당신은 당신이 Consumidadors의 배열을 만들 때

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++; 
    } 
    } 
} 

이 그런 다음에 그들에게 공유 개체를 전달할 실행에 Consumidor.java

다음
public Consumidator(Object monitor) 
{ 
    myMonitor = monitor 
} 

의 생성자에 추가 할 수 있습니다 에 동기화하십시오.

+0

고맙습니다. 내 문제가 해결되었습니다. 너는 위대하다! – Victor