import java.util.concurrent.locks.*;
import java.util.concurrent.atomic.*;
import java.io.*;
public class WorkDone
{
public static void main(String[] args)
throws InterruptedException, IOException
{
int amount=0;
if(args.length>0)
{
try
{
amount=Integer.parseInt(args[0]);
}
catch(NumberFormatException ex)
{
//ignore
}
}
if(amount<1)
{
Runtime runtime = Runtime.getRuntime();
amount=runtime.availableProcessors();
}
System.out.println("Environment:");
System.out.println("java.runtime.name = "+System.getProperty("java.runtime.name"));
System.out.println("java.runtime.version = "+System.getProperty("java.runtime.version"));
System.out.println("java.vendor = "+System.getProperty("java.vendor"));
System.out.println("java.version = "+System.getProperty("java.version"));
System.out.println("java.vm.name = "+System.getProperty("java.vm.name"));
System.out.println("java.vm.info = "+System.getProperty("java.vm.info"));
System.out.println("os.name = "+System.getProperty("os.name"));
System.out.println("os.version = "+System.getProperty("os.version"));
System.out.println("os.arch = "+System.getProperty("os.arch"));
System.out.println("##########################################");
usingSynchronized(amount);
usingFairLock(amount);
usingUnfairLock(amount);
}
public static void usingSynchronized(int threadCount)
throws InterruptedException, IOException
{
perform(threadCount, "usingSynchronized", new SynchronizedLogger());
}
public static void usingFairLock(int threadCount)
throws InterruptedException, IOException
{
perform(threadCount, "usingFairLock", new FairLogger());
}
public static void usingUnfairLock(int threadCount)
throws InterruptedException, IOException
{
perform(threadCount, "usingUnfairLock", new UnfairLogger());
}
private static void perform(int threadCount, String name, AbstractLogger logger)
throws InterruptedException, IOException
{
WorkRunnable[] workRunnables=new WorkRunnable[threadCount];
for(int i=0;i<threadCount;i++)
{
workRunnables[i]=new WorkRunnable(logger);
}
execute(name, workRunnables);
print(name, workRunnables);
logger.close();
}
public static void execute(String text, WorkRunnable[] workRunnables)
throws InterruptedException
{
System.out.println("About to execute "+text+"...");
int threadCount=workRunnables.length;
Thread[] threads=new Thread[threadCount];
for(int i=0;i<threadCount;i++)
{
threads[i]=new Thread(workRunnables[i]);
}
for(int i=0;i<threadCount;i++)
{
threads[i].start();
}
Thread.sleep(10000);
for(int i=threadCount - 1 ; i>=0 ; i--)
{
workRunnables[i].cancel();
}
Thread.sleep(1000); // wait a moment for termination, too lazy for join ;)
}
public static void print(String text, WorkRunnable[] workRunnables)
{
System.out.println("Results for "+text+":");
int totalWorkUnits=0;
for(int i=0;i<workRunnables.length;i++)
{
WorkRunnable current=workRunnables[i];
System.out.println("runnables["+i+"]: "+current);
totalWorkUnits=totalWorkUnits+current.getCounter();
}
System.out.println("Total work-units done: "+totalWorkUnits);
System.out.println("##########################################");
}
public static abstract class AbstractLogger
{
private File file;
private RandomAccessFile raf;
public AbstractLogger()
throws IOException
{
file=File.createTempFile("example",".log");
file.deleteOnExit();
raf=new RandomAccessFile(file, "rw");
}
public File getFile()
{
return file;
}
public abstract void log(String message);
protected void performLogging(String message)
{
try
{
raf.writeChars(message);
}
catch(IOException ex)
{
ex.printStackTrace();
}
/*
System.err.println(message);
try
{
Thread.sleep(10);
}
catch(InterruptedException ex)
{}
*/
}
public void close()
throws IOException
{
raf.close();
}
}
public static class SynchronizedLogger
extends AbstractLogger
{
public SynchronizedLogger()
throws IOException
{
super();
}
public void log(String message)
{
synchronized(this)
{
performLogging(message);
}
}
}
public static class LockLogger
extends AbstractLogger
{
private final ReentrantLock lock;
protected LockLogger(boolean fair)
throws IOException
{
super();
this.lock=new ReentrantLock(fair);
}
public void log(String message)
{
lock.lock();
try
{
performLogging(message);
}
finally
{
lock.unlock();
}
}
}
public static class FairLogger
extends LockLogger
{
public FairLogger()
throws IOException
{
super(true);
}
}
public static class UnfairLogger
extends LockLogger
{
public UnfairLogger()
throws IOException
{
super(false);
}
}
public static class WorkRunnable
implements Runnable
{
private final AtomicBoolean cancel=new AtomicBoolean(false);
private final AbstractLogger logger;
private int counter=0;
private boolean done;
public WorkRunnable(AbstractLogger logger)
{
this.logger=logger;
}
public void cancel()
{
cancel.set(true);
}
public int getCounter()
{
return counter;
}
public boolean isDone()
{
return done;
}
public int fib(int value)
{
if(value == 0)
{
return 0;
}
if(value == 1)
{
return 1;
}
logger.log("Calling fib("+(value-1)+") + fib("+(value-2)+")...");
return fib(value-1)+fib(value-2);
}
public void run()
{
done=false;
for(;;counter++)
{
long value=counter;//fib(counter + 5);
value=value*value*value;
//int value=counter;
logger.log("The calculated value for input "+counter+" is "+value+".");
//logger.log("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
//logger.log("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
if(cancel.get())
{
break;
}
}
done=true;
}
public String toString()
{
return "WorkRunnable[counter="+counter+", done="+done+"]";
}
}
}