import java.io.*;

public class ConcurrentIncrement 
{
	public ConcurrentIncrement(int noThreads) throws Exception
	{
		Increment[] threadObjects = new Increment[noThreads];
		Thread[] threads = new Thread[noThreads];

		for (int i=0; i<noThreads; i++)
		{
			threadObjects[i] = new Increment(this);
		} //for
				
		DataOutputStream dos = new DataOutputStream( new FileOutputStream( "testfile") );
		dos.writeInt( 0 );
		
		for (int i=0; i<noThreads; i++)
		{
			threads[i] = new Thread( threadObjects[i] );
			threads[i].start();
		} //for
		
		for (int i=0; i<noThreads; i++)
		{
			threads[i].join();
		} //for
		
		DataInputStream dis = new DataInputStream( new FileInputStream( "testfile") );
		System.out.println("counter value: "+dis.readInt() );
	} //constructor
	
	public static void main(String argv[]) throws Exception
	{
		ConcurrentIncrement ci = new ConcurrentIncrement(Integer.parseInt(argv[0])); 
	} //main()
	public void addOne()
	{
		try
		{
			DataInputStream dis = new DataInputStream( new FileInputStream( "testfile") );
			int value = dis.readInt();
			
			System.out.println("thread named "+Thread.currentThread().getName()+" read: "+value);
			value++;

			DataOutputStream dos = new DataOutputStream( new FileOutputStream( "testfile") );
			dos.writeInt( value );
			System.out.println("thread named "+Thread.currentThread().getName()+" wrote: "+value);
			
			dis.close();
			dos.close();
		} //try
		catch (IOException ioe)
		{
			System.out.println("An IOException occured\n"+ioe.getMessage());
			ioe.printStackTrace();
			System.exit(1);
		} //catch()
	} //addOne()		
} //class ConcurrentIncrement
// --------------------------------------------------------
class Increment implements Runnable
{
	ConcurrentIncrement ci;
 
 	public Increment(ConcurrentIncrement ci)
 	{
 		this.ci = ci;
 	} //constructor
 
	public void run()
	{
		for (int i=0; i<10; i++)
		{
			ci.addOne();
		} //for
	} //run()
} //class Increment