Java 线程库存控制

Java 线程库存控制,java,multithreading,Java,Multithreading,这是我创建的一个基本应用程序,用于管理仓库的库存。基本上是五个线程或IT公司生产100个小部件,然后将其存储在仓库中。这样做很好,但有时会超过500的仓库限制。因此,我希望五家独立的公司分别生产100个小部件,并将它们存储在仓库中,停止生产500个小部件。然而,目前它有时但并不总是超过限制。因此,如果我运行它三次,它将工作2/3,它将继续向仓库添加大量的小部件。所以我的问题是如何解决这个问题 这是密码 public class mainClass { public static voi

这是我创建的一个基本应用程序,用于管理仓库的库存。基本上是五个线程或IT公司生产100个小部件,然后将其存储在仓库中。这样做很好,但有时会超过500的仓库限制。因此,我希望五家独立的公司分别生产100个小部件,并将它们存储在仓库中,停止生产500个小部件。然而,目前它有时但并不总是超过限制。因此,如果我运行它三次,它将工作2/3,它将继续向仓库添加大量的小部件。所以我的问题是如何解决这个问题

这是密码

public class mainClass {

    public static void main(String[] args) {

        warehouse acct1 = new warehouse(0); // create warehouse with nothing in it
        System.out.print("Reciving widgets...");
        acct1.checkBal();
        manufacturer t1 = new manufacturer(acct1, "Calcutta");  // create 5 threads (manufacturers)
        manufacturer t2 = new manufacturer(acct1, "New York");
        manufacturer t3 = new manufacturer(acct1, "Chicargo");
        manufacturer t4 = new manufacturer(acct1, "Liverpool");
        manufacturer t5 = new manufacturer(acct1, "Tokyo");

        t1.start();                 
        t2.start();
        t3.start();                 
        t4.start();
        t5.start();                 


    }
}
制造商类别

    import java.util.*;
    public class manufacturer extends Thread {
    warehouse myAcct;               //class 'warehouse' assigned to variable MyAcct
     String name;        
        int time;
        Random r = new Random();     // imported from java.util this can be used to create a random amount of time
        int amount = 100;            // This variable is the manufacturing goal of each individual manufacture (thread)`



    public manufacturer(warehouse acct, String x) { 
        myAcct = acct;
        name = x;   // name of the thread
        time = r.nextInt(4000); // This creates the random time of anywhere between 0 and 9999

    }
    public void run() {
        while (true) {              // run forever
            try {
                sleep (time);       // Create new widgets 
            } catch (InterruptedException e) { }
                //  100 by each manufacturer
               try{
                   Thread.sleep(time);
                    System.out.printf("%s has successfully manufactured %d widgets \n", name, amount);

                     //how long do u want to sleep for?
                    //System.out.printf("%s is done\n", name);


                   myAcct.adjustBal(100); System.out.println("widgets have been stored at the central warehouse");
                   System.out.println();
                   Thread.sleep(time);
                }catch(Exception e){}

                    if (myAcct.getBal()  == 500)
                    {
                        System.out.println("The target goal of 500 widgets have been created and delivered to the central warehouse");
                        System.exit(0);
                        //myAcct.adjustBal(100);// with 100 if necessary 

                    }





            } 
            }
        }


    public class warehouse {
    int balance = 0;
    public warehouse(int openingBal) {      // constructor method
        balance = openingBal;
    }
    public synchronized void adjustBal(int amt) {
        balance += amt;         // process a transaction
        checkBal();             // then show the balance
    }
    public void checkBal() {
        System.out.print (balance);

        System.out.println();
    }
    public int getBal() {
        return balance;
    }
}

这里有一个竞赛条件:

        if (myAcct.getBal()  == 500)
        {
            System.out.println("The target goal of 500 widgets have been created and delivered to the central warehouse");
            System.exit(0);
            //myAcct.adjustBal(100);// with 100 if necessary 

        }

在检查和系统之间。退出(0)在系统退出之前,另一个线程仍然可以添加到仓库。

您需要同步对共享变量
balance
的读取和写入,以确保更改可见=>确保
getBalance()
也同步


但问题更可能是由于另一个答案中提到的竞争条件造成的。

您遇到的问题是由以下情况引起的:

假设你有400个项目,现在线程X又增加了100个。当线程X到达平衡检查
if语句时
另一个线程Y可能获得cpu时间并再添加100个(总共给您600个项目),那么平衡检查将永远不会通过

您应该在
adjustBalance
方法中执行限制检查,因为它是同步的,并且确保一次只有一个线程添加检查限制


一个非常重要的注意事项:使用Sturial.Exchange(0)在中间中止进程是一个非常糟糕的编程。您应该阅读有关生产者/消费者的信息,了解如何在单个数据结构上管理多个线程。

类名应以大写字母开头,如
MainClass
,这看起来像是一个家庭作业问题。还有芝加哥,不是芝加哥。