Semáforo em java

Galera, gostaria da ajuda de vocês, estou tentando implementar um código utilizando semaphore.

import java.util.concurrent.Semaphore;
//package primeiroprograma; 
//Colocado pelo NetBeans
/**
 *
 * @author Victtor Araújo Freitas
 */
public class PrimeiroPrograma {//Nome da Classe
    int contador=0;//Contador que irei utilizar, como se fosse uma variavel global
    Semaphore semaforo;
    public PrimeiroPrograma(){//Um metodo
        try {//Necessário para o uso do sleep, pois é um tratamento caso haja interrupção
            Semaphore semaforo = new Semaphore(1);
            testandoThread td = new testandoThread();//Crio a Thread1
            outraThread tds = new outraThread();//Crio a Thread 2
            td.start();// inicio a primeira Thread
            //testandoThread.sleep(100);//Essa parte é para solucionar o problema, com esse sleep as threads sicronizam, chegando ao resultado de 7000000 
            tds.start();//Inicio a segunda Thread
            testandoThread.sleep(100);//Sleep<- Colocando pra dormir para que de tempo das threads executarem
            System.out.println(contador);//Imprimir na tela o valor da variavel contador
        } catch (InterruptedException ex) {}

    }
    public static void main(String[] args) {
       new PrimeiroPrograma();
       
    }
    public class testandoThread extends Thread{
        public void run(){
            System.out.println("Comecei Thread 1");
            int i;
            for(i=0;i<1000000;i++){
             try{
                    semaforo.acquire();
                    contador= contador+5;
                } catch(InterruptedException e){
                    //e.printStackTrace();
                } finally{
                    semaforo.release();
                }
            }
            System.out.println("Terminei Thread 1");
        }
    }
    public class outraThread extends Thread{
        public void run(){
            System.out.println("Comecei Thread 2");
            int i;
            for(i=0;i<1000000;i++){
             try{
                    semaforo.acquire();
                    contador= contador+2;
                } catch(InterruptedException e){
                  //  e.printStackTrace();
                } finally{
                    semaforo.release();
                }
            }
            System.out.println("Terminei Thread 2");
        }
    }
}

ERRO:

Exception in thread “Thread-0” java.lang.NullPointerException
at PrimeiroPrograma$testandoThread.run(PrimeiroPrograma.java:38)

Mas ta dando erro e não sei bem o que devo mudar para funcionar.

Teu problema tem a ver com o fato de você estar acessando um objeto antes dele ser construído. Você está startando as threads dentro do construtor, e esse é um momento perigoso. Nenhuma referência para um objeto deve ser publicada (ou vazar do escopo) antes de seu construtor retornar, pois existe o perigo de outra thread acessar aquele objeto, causando problemas como NullPointerExceptions.

Se quiser ler mais sobre isso, existe um livro espetacular chamado Java Concurrency in Practice: http://jcip.net/.

Experimente colocar esse código que inicia as threads em um outro método, fora do construtor. No main, você vai fazer:

public static void main() {
    PrimeiroPrograma p = new PrimeiroPrograma();
    p.metodoQueIniciaAsThreads();
}

Na sua classe PrimeiroPrograma você declarou a seguinte variável de instância:

Semaphore semaforo;

Esta váriavel é utilizada pelas classes testandoThread e outraThread.

Entretanto no construtor da classe PrimeiroPrograma você não está inicializando a variável de instância, você está instanciando uma variável local de mesmo nome:

Semaphore semaforo = new Semaphore(1);

Altere para ficar assim:

this.semaforo = new Semaphore(1);

2 curtidas