Java 无法在多线程中实现同步

Java 无法在多线程中实现同步,java,multithreading,synchronization,java-threads,Java,Multithreading,Synchronization,Java Threads,我基本上是在尝试实现一个现实生活中的例子,多人在线预订一辆出租车。在我的代码中,我有3个类-出租车、客户和服务器必须有多个客户(线程)和一辆出租车。但我不能这么做。每次我创建新客户时,都会创建一个新的出租车实例。 这是出租车等级代码- public class taxi { boolean BOOKED=false; String id; void book(){ try { Th

我基本上是在尝试实现一个现实生活中的例子,多人在线预订一辆出租车。在我的代码中,我有3个类-出租车、客户和服务器
必须有多个客户(线程)和一辆出租车。但我不能这么做。每次我创建新客户时,都会创建一个新的出租车实例。
这是出租车等级代码-

    public class taxi  {
        boolean BOOKED=false;
         String id;
        void book(){
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            BOOKED=true;
            System.out.println("Customer "+Thread.currentThread().getName()+" BOOKED taxi");
        }

        void release(){
            BOOKED=false;
            System.out.println("Customer "+Thread.currentThread().getName()+" RELEASED taxi");
        }

        void setId(String id){
            this.id=id;
        }

        String getId(){
            return id;
        }

    }
客户类别代码-

public class customer extends Thread {
     taxi t=new taxi();
        public  void run(){
            //System.out.println(t.hashCode());
            t.setId(Thread.currentThread().getName());
            System.out.println("Customer "+Thread.currentThread().getName()+" trying to BOOK taxi");
            t.book();
            System.out.println("Customer "+Thread.currentThread().getName()+" is currently USING taxi");

            try {


Thread.sleep(2000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println("Customer "+Thread.currentThread().getName()+" RELEASING taxi");
        t.release();
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println("taxi used by customer "+Thread.currentThread().getName()+" set id to "+t.getId());
    }



}
public class server {

public static void main(String args[]){

         customer A=new customer();
         customer B=new customer();
         customer C=new customer();
         customer D=new customer();
        Thread t=new Thread();
         A.setName("A");
         B.setName("B");
         C.setName("C");
         D.setName("D");

         A.start();
         B.start();
         C.start();
         D.start();




    }


    }
服务器类代码-

public class customer extends Thread {
     taxi t=new taxi();
        public  void run(){
            //System.out.println(t.hashCode());
            t.setId(Thread.currentThread().getName());
            System.out.println("Customer "+Thread.currentThread().getName()+" trying to BOOK taxi");
            t.book();
            System.out.println("Customer "+Thread.currentThread().getName()+" is currently USING taxi");

            try {


Thread.sleep(2000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println("Customer "+Thread.currentThread().getName()+" RELEASING taxi");
        t.release();
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println("taxi used by customer "+Thread.currentThread().getName()+" set id to "+t.getId());
    }



}
public class server {

public static void main(String args[]){

         customer A=new customer();
         customer B=new customer();
         customer C=new customer();
         customer D=new customer();
        Thread t=new Thread();
         A.setName("A");
         B.setName("B");
         C.setName("C");
         D.setName("D");

         A.start();
         B.start();
         C.start();
         D.start();




    }


    }

这是我的输出-

Customer B trying to BOOK taxi
Customer D trying to BOOK taxi
Customer A trying to BOOK taxi
Customer C trying to BOOK taxi
Customer B BOOKED taxi
Customer A BOOKED taxi
Customer A is currently USING taxi
Customer D BOOKED taxi
Customer D is currently USING taxi
Customer B is currently USING taxi
Customer C BOOKED taxi
Customer C is currently USING taxi
Customer C RELEASING taxi
Customer C RELEASED taxi
Customer D RELEASING taxi
Customer D RELEASED taxi
Customer A RELEASING taxi
Customer A RELEASED taxi
Customer B RELEASING taxi
Customer B RELEASED taxi
taxi used by customer D set id to D
taxi used by customer C set id to C
taxi used by customer A set id to A
taxi used by customer B set id to B


正如您所看到的,每辆出租车的id是不同的,而不是相同的。
请帮助。

我认为,出租车等级不必是一条线索。通过将滑行类作为所有其他客户线程之间的共享资源(使用同步方法的单吨),我们可以在多线程中实现预期的同步。

我认为,滑行类不必是线程。通过将滑行类作为所有其他客户线程之间的共享资源(单吨同步方法),我们可以在多线程中实现预期的同步。

有关代码的一些要点:


  • 您应该只创建Taxi类的一个实例,并从Customer类中删除Taxi实例变量,并在server类中实例化Taxi
  • 将您的客户类别更改为在共享出租车上工作。您可以在Customer类中创建一个参数化构造函数来初始化共享出租车
  • 应该在方法书内调用setId,这样的士的Id只能由想要预订的士的线程更改 在出租车类中,您可以通过这种方式使用等待/通知机制来实现同步:

    public class Taxi {
        Boolean BOOKED = false;
        String id;
    
        void book() throws InterruptedException {
            synchronized (this) {
                while (BOOKED) {
                    this.wait();
                }
                try {
                    setId(Thread.currentThread().getName());
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                BOOKED = true;
                System.out.println("Customer " + Thread.currentThread().getName() + " BOOKED taxi");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    
        void release() throws InterruptedException {
            synchronized (this) {
                BOOKED = false;
                System.out.println("Customer " + Thread.currentThread().getName() + " RELEASED taxi");
                this.notifyAll();
            }
        }
    
        void setId(String id) throws InterruptedException {
            System.out.println("SETTING ID TO CUSTOMER " + Thread.currentThread().getName());
            this.id = id;
        }
    
        String getId() {
            return id;
        }
    }
    
    客户:

       public class Customer extends Thread {
        Taxi taxi;
    
        public Customer(Taxi taxi){
            this.taxi = taxi;
        }
    
        public  void run(){
            //System.out.println(t.hashCode());
    
            System.out.println("Customer "+Thread.currentThread().getName()+" trying to BOOK taxi");
            try {
                taxi.book();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("Customer "+Thread.currentThread().getName()+" is currently USING taxi");
    
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            System.out.println("Customer "+Thread.currentThread().getName()+" RELEASING taxi");
            try {
                taxi.release();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
    

    关于代码的一些要点:


  • 您应该只创建Taxi类的一个实例,并从Customer类中删除Taxi实例变量,并在server类中实例化Taxi
  • 将您的客户类别更改为在共享出租车上工作。您可以在Customer类中创建一个参数化构造函数来初始化共享出租车
  • 应该在方法书内调用setId,这样的士的Id只能由想要预订的士的线程更改 在出租车类中,您可以通过这种方式使用等待/通知机制来实现同步:

    public class Taxi {
        Boolean BOOKED = false;
        String id;
    
        void book() throws InterruptedException {
            synchronized (this) {
                while (BOOKED) {
                    this.wait();
                }
                try {
                    setId(Thread.currentThread().getName());
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                BOOKED = true;
                System.out.println("Customer " + Thread.currentThread().getName() + " BOOKED taxi");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    
        void release() throws InterruptedException {
            synchronized (this) {
                BOOKED = false;
                System.out.println("Customer " + Thread.currentThread().getName() + " RELEASED taxi");
                this.notifyAll();
            }
        }
    
        void setId(String id) throws InterruptedException {
            System.out.println("SETTING ID TO CUSTOMER " + Thread.currentThread().getName());
            this.id = id;
        }
    
        String getId() {
            return id;
        }
    }
    
    客户:

       public class Customer extends Thread {
        Taxi taxi;
    
        public Customer(Taxi taxi){
            this.taxi = taxi;
        }
    
        public  void run(){
            //System.out.println(t.hashCode());
    
            System.out.println("Customer "+Thread.currentThread().getName()+" trying to BOOK taxi");
            try {
                taxi.book();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("Customer "+Thread.currentThread().getName()+" is currently USING taxi");
    
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            System.out.println("Customer "+Thread.currentThread().getName()+" RELEASING taxi");
            try {
                taxi.release();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
    

    为什么每次在客户中创建新的出租车?问题是:
    taxi t=new taxi()。只需通过构造函数传递出租车,或使其成为全局的或类似的。这样,每位顾客都将乘坐同一辆出租车。此外,线程是危险的,所以你应该非常小心使用它们。您没有任何同步。我建议你不了解如何正确使用线程。我建议您阅读有关
    同步
    易失性
    等待
    通知
    通知所有
    ,并尝试一些基本示例。我觉得头两个在
    headfirstjava
    中描述得很好。
    Offtopic:在命名变量和方法时,应该遵循约定。

    为什么每次在客户中创建新的出租车时都要这样做?问题是:
    taxi t=new taxi()。只需通过构造函数传递出租车,或使其成为全局的或类似的。这样,每位顾客都将乘坐同一辆出租车。此外,线程是危险的,所以你应该非常小心使用它们。您没有任何同步。我建议你不了解如何正确使用线程。我建议您阅读有关
    同步
    易失性
    等待
    通知
    通知所有
    ,并尝试一些基本示例。我觉得头两个在
    headfirstjava
    中描述得很好。

    Offtopic:在命名变量和方法时,应该遵循约定。

    您认为如何
    taxi t=new taxi()
    是否作为
    customer
    中的一个字段?它在customer中创建一个taxi实例。我知道这是我的问题的根本原因,但我想不出其他方法来解决这个问题。创建一个
    taxi
    实例,并在您的
    客户
    实例中共享。你以前学过构造函数参数吗?是的,我知道客户参数。您能告诉我执行此操作的确切代码吗?不幸的是,不能。请使用构造函数参数在每个
    customer
    实例中设置
    taxi
    字段。使用相同的
    taxi
    实例作为您创建的每个
    客户的参数
    是否作为
    customer
    中的一个字段?它在customer中创建一个taxi实例。我知道这是我的问题的根本原因,但我想不出其他方法来解决这个问题。创建一个
    taxi
    实例,并在您的
    客户
    实例中共享。你以前学过构造函数参数吗?是的,我知道客户参数。您能告诉我执行此操作的确切代码吗?不幸的是,不能。请使用构造函数参数在每个
    customer
    实例中设置
    taxi
    字段。使用相同的
    taxi
    实例作为您创建的每个
    customer
    的参数。您能告诉我如何使用wait()和notify()等方法吗?您能告诉我如何使用wait()和notify()等方法吗?我想您误解了这个问题。这里的问题是,我最终拥有了多个taxi类实例,而且由于taxi类充当了我的数据,我不能拥有多个实例。您应该只创建一个taxi类实例,并从Customer类中删除taxi实例变量,然后在server ClassOK中实例化taxi。那么我如何进一步使用该实例,以便所有线程都在同一个实例上工作请看上面的答案,我猜您误解了这个问题。这里的问题是,我最终拥有了多个taxi类的实例,并且由于taxi类充当了我的数据,所以我不能拥有它的多个实例