Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Thread starts running and terminates itself


Update : Thanks everyone! I've modified the program as per the suggestions and the code given below is the modified code.


Original Post : I've gone through some "Apply and Analyze" type of questions and in one question, the programmer has been asked to apply multithreading concept for three reservation counters of a cinema theater and calculate the total booking numbers and amount collected in a show.

And I've written a program for the same which you can see below:

import java.io.*;
import java.lang.*;

class Cinema
{
    int no=0,price=0;
    synchronized void reservation(int n,int p)
    {
        no=no+n;
        price=price+p;
    }
}


class Counter implements Runnable
{
    BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
    Cinema c;
    int not,cost;
    Counter(Cinema c)
    {
        this.c=c;
    }
    public void run()
    {
        try
        {
            System.out.print("\nCounter 1");
            System.out.print("\nEnter the no. of tickets :");
            not=Integer.parseInt(br.readLine());
            cost=not*150;
            c.reservation(not,cost);
        }
        catch(IOException e){System.out.print("\n"+e);}
    }
}

class CinemaMain
{
    public static void main(String args[])throws IOException
    {
        Cinema c=new Cinema();
        System.out.print("\nCounter 1");
        Thread c1=new Thread(new Counter(c));
        c1.start();
        c1.join();
        System.out.print("\nCounter 2");
        Thread c2=new Thread(new Counter(c));
        c2.start();
        c2.join();
        System.out.print("\nCounter 3");
        Thread c3=new Thread(new Counter(c));
        c3.start();
        c3.join();
        try
        {
            Thread.sleep(500);
        }
        catch(InterruptedException ie)
        {
            System.out.print("\n"+ie);
        }
        System.out.print("\nTotal no. of tickets :"+c.no);
        System.out.print("\nTotal Money collected:"+c.price);
    }
}

I can compile it just fine, but when I run the program, this is what I get -->LINK (since I don't have 10 reputation, I couldn't post the image here, sorry!) I don't know why, it doesn't ask for input even though I've written the code to get input in the run method.

like image 874
Sivaprasanna Sethuraman Avatar asked Jan 23 '26 11:01

Sivaprasanna Sethuraman


2 Answers

I can compile it just fine, but when I run the program, this is what I get ...

There are a couple of things wrong with your program:

  1. The main thread is not waiting for the Counter threads to finish before it prints out the totals. If you need to wait for a thread to complete then you call thread.join() on it.

    Thread counter1 = new Thread(new Counter1(c));
    counter1.start();
    // start other threads here...
    // now wait for the counter1 to finish
    counter1.join();
    

    In your case, the 3 Counters are forked but the main only sleeps a bit and then quits. The Counter threads are still running.

  2. Each of the Counter threads is adding values to fields inside the Cinema but there is no synchronization in Cinema. Anytime two threads are modifying the same field, there must be some mutex protection and memory synchronization.

    The easy thing to do here is to make the Cinema.reservation(...) method be synchronized. Then each of the Counter objects will get a lock on the Cinema instance which will ensure only one Counter updates the Cinema at one time. The synchronized keyword also ensures that the fields in the Cinema object are memory synchronized as well.

    synchronized void reservation(int n,int p) { ...
    
  3. As always, you should consider using the ExecutorService classes instead of forking threads yourself. See the Java tutorial.

like image 65
Gray Avatar answered Jan 24 '26 23:01

Gray


Try this Approach ;

import java.io.*;
import java.lang.*;

public class Cinema
{
    int no=0,price=0;
    synchronized void reservation(int n,int p)
    {
        no=no+n;
        price=price+p;
    }

    public static void main(String args[])throws IOException, InterruptedException
    {
        Cinema c=new Cinema();
        Thread t1 = new Thread(new Counter(c,"Counter 1"));
        t1.start();
        Thread t2 = new Thread(new Counter(c,"Counter 2"));
        t2.start();
        Thread t3 = new Thread(new Counter(c,"Counter 3"));
        t3.start();

        t1.join();
        t2.join();
        t3.join();
        try
        {
            Thread.sleep(100);
        }
        catch(InterruptedException ie)
        {
            System.out.print("\n"+ie);
        }
        System.out.print("\nTotal no. of tickets :"+c.no);
        System.out.print("\nTotal Money collected:"+c.price);
    }
}


class Counter implements Runnable
{
    BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
    Cinema c;
    int not,cost;
    String counterName;
    Counter(Cinema c,String counterName)
    {
        this.c=c;
        this.counterName=counterName;
    }
    public void run()
    {
        try
        {
            synchronized(c) {
            System.out.print("\n" + counterName);
            System.out.print("\nEnter the no. of tickets :");
            not=Integer.parseInt(br.readLine());
            cost=not*150;
            c.reservation(not,cost);
            }
        }
        catch(IOException e){System.out.print("\n"+e);}
    }
}
  1. I have made a single Counter class instead of 3 classes you are using.

  2. I made the reservation method to be synchronized.

  3. I called join method on all the three threads. So the program will not terminate abruptly.TGhe last thread that would teminate would be main.

  4. In run() method , I locked the Cinema object c. This will resolve your issue of Buffered Reader at this moment of time. But in real world scenario different threads will be run by different people. So no need to lock the Cinema object there.it is just for your usage.

like image 40
Nishant Lakhara Avatar answered Jan 24 '26 23:01

Nishant Lakhara