class SpecialBarriera{
private int numeroThreads, threadArrivati;
boolean nera;
ReentrantLock lock = new ReentrantLock();
Condition cond = lock.newCondition();
public SpecialBarriera(int numeroThreads){
this.numeroThreads = numeroThreads;
this.threadArrivati = 0;
this.nera = false;
}
public void awaitT(){
lock.lock();
while(threadArrivati < numeroThreads)
try {
cond.await();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
lock.unlock();
}
public void doneT(){
lock.lock();
++threadArrivati;
if(threadArrivati == numeroThreads)
cond.signal();
lock.unlock();
}
public boolean awaitP(){
lock.lock();
while(nera == false && threadArrivati < numeroThreads)
try {
cond.await();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
lock.unlock();
return nera;
}
public void reset(){
lock.lock();
while(threadArrivati < numeroThreads)
try {
cond.await();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
numeroThreads = 0;
lock.unlock();
}
public void doneP(boolean nera){
lock.lock();
++numeroThreads;
if(nera)
this.nera = true;
cond.signal();
lock.unlock();
}
}
class Pecora{
private boolean bianca;
public Pecora(){
bianca = true;
}
public void vernicia(){
bianca = false;
}
public boolean isBianca(){
return bianca;
}
public void tosa() {
bianca = true;
}
}
class Gregge{
private static final int numeroThreads = 4;
private Pecora[] gregge;
private ReentrantLock lock;
private Condition cond;
private int pastori, tosatori,lupi;
public Gregge(int dimensione){
this.gregge = new Pecora[dimensione];
this.lock = new ReentrantLock();
this.cond = lock.newCondition();
this.pastori = 0;
this.tosatori = 0;
this.lupi = 0;
}
public void takePastoreLock(){
lock.lock();
while(lupi > 0 || tosatori > 0)
try {
cond.await();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
++pastori;
lock.unlock();
}
public void takeLupoLock(){
lock.lock();
while(pastori > 0 || tosatori > 0)
try {
cond.await();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
++lupi;
lock.unlock();
}
public void takeTosatoreLock(){
lock.lock();
while(lupi > 0 || pastori > 0)
try {
cond.await();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
++tosatori;
lock.unlock();
}
public void leaveLupoLock(){
lock.lock();
--lupi;
if(lupi == 0)
cond.signalAll();
lock.unlock();
}
public void leaveTosatoreLock(){
lock.lock();
tosatori = 0;
cond.signalAll();
lock.unlock();
}
public void leavePastoreLock(){
lock.lock();
pastori = 0;
cond.signalAll();
lock.unlock();
}
public void startGregge(){
for(int i = 0; i<gregge.length; i++)
gregge[i] = new Pecora();
Lupo lupo1 = new Lupo(this);
Lupo lupo2 = new Lupo(this);
lupo1.start();
lupo2.start();
Display display = new Display(this);
display.start();
}
public boolean esistePecoraNera(){
int k = numeroThreads;
int fetta;
SpecialBarriera barriera = new SpecialBarriera(numeroThreads);
while((fetta = gregge.length/numeroThreads) == 0)
--k;
Pastore[] pastori = new Pastore[k];
for(int i = 0; i<k-1;i++){
takePastoreLock();
pastori[i] = new Pastore(fetta*i,fetta*(i+1)-1,gregge,barriera);
pastori[i].start();
}
takePastoreLock();
pastori[k-1] = new Pastore(fetta*(k-1),gregge.length-1,gregge,barriera);
pastori[k-1].start();
boolean nera = barriera.awaitP();
//BUG perchè i thread non finiscono in realtà....
leavePastoreLock();
return nera;
}
public void tosaTutte(){
int x = numeroThreads;
int fetta;
SpecialBarriera barriera = new SpecialBarriera(numeroThreads);
while((fetta = gregge.length/numeroThreads) == 0)
--x;
Tosatore[] tosatori = new Tosatore[x];
for(int i = 0; i<x-1;i++){
takeTosatoreLock();
tosatori[i] = new Tosatore(fetta*i,fetta*(i+1)-1,gregge,barriera);
tosatori[i].start();
}
takeTosatoreLock();
tosatori[x-1] = new Tosatore(fetta*(x-1),gregge.length-1,gregge,barriera);
tosatori[x-1].start();
barriera.awaitT();
for(int i= 0; i<gregge.length; i++)
if(gregge[i].isBianca())
System.out.print("O");
else System.out.print("@");
System.out.println();
leaveTosatoreLock();
}
public void alteraColore() {
takeLupoLock();
// attualmente becca anche le nere XD
int rand = (int) (Math.random()*gregge.length);
gregge[rand].vernicia();
leaveLupoLock();
}
public void stampa() {
lock.lock();
int i = 0;
int k = gregge.length/5;
for(int j = 1; j<=k; j++){
for(; i<j*5;i++)
if(gregge[i].isBianca())
System.out.print("O");
else System.out.print("@");
System.out.println("");
}
for(; i<gregge.length;i++)
if(gregge[i].isBianca())
System.out.print("O");
else System.out.print("@");
System.out.println("]");
lock.unlock();
}
}
class Display extends Thread{
private Gregge gregge;
public Display(Gregge gregge){
this.gregge = gregge;
}
@Override
public void run() {
while(true){
try {
sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
gregge.stampa();
}
}
}
class Lupo extends Thread{
Gregge gregge;
public Lupo(Gregge gregge){
this.gregge = gregge;
}
@Override
public void run() {
while(true){
try {
sleep((int)(1000));
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
gregge.alteraColore();
}
}
}
class Pastore extends Thread{
private int min;
private int max;
private Pecora[] gregge;
private SpecialBarriera barriera;
public Pastore(int min, int max, Pecora[] gregge, SpecialBarriera barriera){
this.min = min;
this.max = max;
this.gregge = gregge;
this.barriera = barriera;
}
@Override
public void run() {
boolean nera = false;
for(; min <= max; min++)
if(!gregge[min].isBianca())
nera = true;
barriera.doneP(nera);
}
}
class Tosatore extends Thread{
private int min;
private int max;
private Pecora[] gregge;
private SpecialBarriera barriera;
public Tosatore(int min, int max, Pecora[] gregge, SpecialBarriera barriera){
this.min = min;
this.max = max;
this.gregge = gregge;
this.barriera = barriera;
}
@Override
public void run() {
System.out.println(min+" "+max);
for(; min <= max; min++)
if(!gregge[min].isBianca()){
gregge[min].tosa();
}
barriera.doneT();
}
}
public class GreggeMain {
public static void main(String[] args) {
Gregge gregge = new Gregge(11);
gregge.startGregge();
while(true){
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if(gregge.esistePecoraNera())
gregge.tosaTutte();
}
}
}