线程开始运行并自行终止。

3

更新:谢谢大家!根据建议,我修改了程序,并且下面给出的代码是修改后的代码。


原始帖子:我看过一些“申请和分析”类型的问题,在一个问题中,程序员被要求为电影院的三个预订柜台应用多线程概念,并计算在一场演出中的总预订人数和收取的总金额。

我已经为此编写了一个程序,您可以在下方看到:

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);
    }
}

我可以编译它,但是运行程序时,我得到了这个 -->链接(由于我没有10的声望,我无法在此处发布图像,抱歉!)我不知道为什么,尽管我已经在run方法中编写了输入代码,但它却没有要求输入。

考虑使用 Scanner 来处理控制台输入。 - Sotirios Delimanolis
为什么你需要3个线程? - Chriss
4
这是什么疯狂的做法?为什么不能只有一个计数器类并创建三个它的实例? - dimoniy
请注意,run() 方法只运行一次,然后线程就完成并关闭了。你的每个计数器类(它们是相同的类,为什么要复制/粘贴三次?)将运行一次并终止。 - Mike 'Pomax' Kamermans
3个回答

5
我可以编译它,但是运行程序时,我得到了这个结果...
你的程序有几个问题:
  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.


太棒了...真的很有帮助!由于我是Java的新手,所有这些线程和小应用程序的概念对我来说有点困难,但像你这样的人真的很有帮助,再次感谢你的解释 :) - Sivaprasanna Sethuraman

1
尝试这种方法;
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. 我已经制作了一个单一的计数器类,代替了你使用的3个类。

  2. 我将预订方法设为同步。

  3. 我在所有三个线程上调用了join方法。因此程序不会突然终止。最后一个终止的线程将是主线程。

  4. 在run()方法中,我锁定了Cinema对象c。这将解决您目前遇到的BufferedReader问题。但在真实世界的情况下,不同的人将运行不同的线程。所以不需要在那里锁定Cinema对象,这只是为了您的使用。


1
谢谢!但是我已经更新了。无论如何,再次感谢您尝试帮助我! :) - Sivaprasanna Sethuraman

0
为什么你需要创建线程,而不是选择更简单的方式呢?
import java.io.*;
import java.lang.*;
import java.util.Scanner;

public class Cinema {

   public Cinema(){

int no=0,price=0;


}

public int Count () {



int not,not2, not3, cost,cost2,cost3;




        System.out.print("\nCounter 1");
        System.out.print("\nEnter the no. of tickets: ");
        Scanner br=new Scanner(System.in);
        String input=br.nextLine();
        not=Integer.parseInt(input);
        cost=not*150;

        System.out.println("Cost of tickets: "+cost);


        System.out.print("\nCounter 2");
        System.out.print("\nEnter the no. of tickets: ");
        Scanner br2=new Scanner(System.in);
        String input2=br2.nextLine();
        not2=Integer.parseInt(input2);
        cost2=not2*150;

        System.out.println("Cost of tickets: "+cost2);


        System.out.print("\nCounter 3");
        System.out.print("\nEnter the no. of tickets: ");
        Scanner br3=new Scanner(System.in);
        String input3=br3.nextLine();
        not3=Integer.parseInt(input3);
        cost3=not3*150;

        System.out.println("Cost of tickets: "+cost3);

        int total=cost+cost2+cost3;
        int tickets=not+not2+not3;
        System.out.println("Total price for tickets is: "+total);
        System.out.println("Total number of tickets is: "+tickets);
        return total;


 }



public  static void main(String args[])
{
    Cinema c=new Cinema();
    c.Count();


  }





 }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接