ActiveMQ 5.8.0 事務相關示例程序分析

ActiveMQ 5.8.0 事務相關示例程序分析

 

示例程序在版本中的位置:apache-activemq-5.8.0\example\transactions

 

1. 概述

 

該示例程序模擬了一個電腦採購的過程:零售商(Retailer)向中間商(Vendor)下訂單訂購電腦,中間商收到訂單後,

向供應商(Supplier)訂購電腦配件(存儲硬件和顯示器).

 

示例中用3個類分別模擬Retailer,Vendor和Supplier.

 

然後使用TransactionsDemo類同時執行Retailer,Vendor和Supplier,

因爲供應商有兩個,所以啓動了兩個Supplier線程.

 

    Retailer r = new Retailer(url, user, password);

    Vendor v = new Vendor(url, user, password);

    Supplier s1 = new Supplier("HardDrive", "StorageOrderQueue", url, user, password);

    Supplier s2 = new Supplier("Monitor", "MonitorOrderQueue", url, user, password);

 

    new Thread(r, "Retailer").start();

    new Thread(v, "Vendor").start();

    new Thread(s1, "Supplier 1").start();

    new Thread(s2, "Supplier 2").start();

 

2. Retailer

 

   Retailer沒有使用事務.該類向VendorOrderQueue隊列發送Map類型的訂單消息.

   

   並創建了一個臨時消息目的地用來接收Vendor類處理VendorOrderQueue隊列中

   訂單消息之後發送的反饋.

   

   發送5個訂單之後,發送一個空消息來結束當前線程.

   

   當一個訂單消息發送之後,Retailer類使用replyConsumer.receive();方法同步接收

   Vendor的反饋,當訂單正常處理完成後,Vendor類發送反饋給Retailer,Retailer收到

   反饋後,才發送下一個訂單消息.

   

3. Vendor

 

   Vendor類同步接收VendorOrderQueue隊列隊列中的消息,異步接收Supplier的反饋.

   Vendor接收到VendorOrderQueue隊列中的訂單消息之後,發送兩個消息給對應的Supplier

   然後接收Supplier的反饋,當兩個Supplier都正常反饋之後,再發送反饋消息給Retailer,通知

   訂單處理情況.

   

   Vendor使用了事務,將從VendorOrderQueue接收消息和向兩個Supplier發送消息放到一個事務中.

   只有同時正常接收了VendorOrderQueue的訂單消息和向StorageOrderQueue和MonitorOrderQueue

   發送消息之後才提交事務,否則回滾事務.

   

   Vendor處理Supplier確認消息分析:

   Vendor本身實現了MessageListener接口,並將自身註冊爲Supplier確認消息目的地的Listener.

   confirmConsumer.setMessageListener(this);

   

   Vendor使用了一個內部類Order來作爲輔助類來處理Supplier的確認消息.

   Supplier確認消息消費者confirmConsumer異步處理確認消息.

   有一點需要注意,:JMS1.1規範中規定,Session使用單一線程

   來運行所有的MessageListener,當線程在執行一個監聽器時,所有其他被異步轉發的消息必須等待.

   上述規範對理解Order類的處理方式有幫助.

   

   Vendor在接收到訂單消息之後,會new一個Order對象,new Order(message);新建對象時,

   Order內部使用pendingOrders.put(orderNumber, this);方法保存每一個訂單對象,

   pendingOrders   = new HashMap<Integer, Order>();pendingOrders根據訂單編號(1-5)映射訂單.

   new Order(message);後,新建Order的Status爲Pending

   

   Vendor使用MessageListener處理Supplier確認消息時,也是根據訂單編號獲取保存在

   pendingOrders中的Order實例的.

   

   處理Supplier確認消息時,先執行下面代碼:

   orderNumber = componentMessage.getInt("VendorOrderNumber");

   Order order = Order.getOrder(orderNumber);

   order.processSubOrder(componentMessage);

   asyncSession.commit(); //這裏是爲了確認消息已被處理(只處理了一個Supplier的確認消息).因爲asyncSession創建方式爲

   //asyncSession = asyncconnection.createSession(true, Session.SESSION_TRANSACTED);

   //使用了Session.SESSION_TRANSACTED

   

   其中processSubOrder,是真正處理Supplier確認消息的.參數componentMessage是Supplier發送的確認消息.

   Order中使用monitor和storage來保存兩個Supplier的確認消息,當這兩個字段不爲null時,表示訂單處理完了.

   然後將Oreder的Status狀態變成Fulfilled(如果處理錯誤,則Oreder的Status變成Canceled).

   

   回到MessageListener的OnMessage中的如下代碼:

   

      if (!"Pending".equals(order.getStatus()))

      {

        System.out.println("Vendor: Completed processing for order " + orderNumber);

 

        MessageProducer replyProducer = asyncSession.createProducer(order.getMessage().getJMSReplyTo());

        MapMessage replyMessage = asyncSession.createMapMessage();

        if ("Fulfilled".equals(order.getStatus()))

        {

          replyMessage.setBoolean("OrderAccepted", true);

          System.out.println("Vendor: sent " + order.quantity + " computer(s)");

        }

        else

        {

          replyMessage.setBoolean("OrderAccepted", false);

          System.out.println("Vendor: unable to send " + order.quantity + " computer(s)");

        }

        replyProducer.send(replyMessage);

        asyncSession.commit();

        System.out.println("Vender: committed transaction 2");

      }

      

   當Order的Status不是Pending時,一個訂單的兩個Supplier確認消息處理完畢了.然後發送訂單確認消息給Retailer,

   因爲使用了事務,所以調用asyncSession.commit();提交發送消息.

   

   這裏使用了事務,但是處理Supplier的確認消息時,沒有回退(rollback).

   

4. Supplier

   Supplier類使用事務,同步接收Vendor的消息,處理完之後,發送確認消息給Vendor.

   

   

5.程序如何結束

 

  首先Retailer發送完5個訂單消息之後,會一個空消息(非Map)消息給Vendor,表示結束程序.

  // Send a non-MapMessage to signal the end

  producer.send(session.createMessage());

  

  Vender收到空消息之後,也會發送兩個空消息給Supplier,並調用break結束線程調用.

  else// if (inMessage instanceof MapMessage)

  {

    // end of stream

    Message outMessage = session.createMessage();

    outMessage.setJMSReplyTo(vendorConfirmQueue);

    monitorProducer.send(outMessage);

    storageProducer.send(outMessage);

    session.commit();

    break;

  }

  

  Supplier收到空消息之後,發送空消息作爲確認消息,然後使用break結束線程調用.

  else

  {

    // End of Stream

    producer.send(session.createMessage());

    session.commit();

    producer.close();

    break;

  }

  

  Vendor在發送了5個訂單消息之後,發送一個空消息,然後將線程wait(),並監控numSuppliers,

  當numSuppliers>0時表示還有空的Supplier確認消息需要處理.

  

  Vendor的MessageListener收到空的Supplier確認消息之後,先將numSuppliers--,然後通知Vendor繼續Run.

  收到第二個Supplier確認消息之後,Vendor繼續Run,此時不用在wait()了.

  

  然後,即可執行

  synchronized (supplierLock)

  {

    while (numSuppliers > 0)

    {

      try

      {

        supplierLock.wait();

      }

      catch (InterruptedException e)

      {

        e.printStackTrace();

      }

    }

  }

  

  之後的代碼:

  connection.close();

  asyncconnection.close();

  

  這裏使用同步,是爲了保證MessageListener處理完畢之後纔可以調用下面的代碼來關閉connection和asyncconnection(session)

  connection.close();

  asyncconnection.close();

  

P.S. JMS1.1規範中關於事務的描述:

當事務提交時,輸入原子單元被確認,輸出原子單元被髮送。

如果事務回滾,則它生產的消息被銷燬,它消費的消息被自動恢復。

  

 源碼:

package com.jackyin.testamqtran;

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE
 * file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file
 * to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
 * License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by
 * applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
 * governing permissions and limitations under the License.
 */
import org.apache.activemq.ActiveMQConnectionFactory;
import javax.jms.Connection;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.MapMessage;
import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TemporaryQueue;

/**
 * The Retailer orders computers from the Vendor by sending a message via
 * the VendorOrderQueue. It then syncronously receives the reponse message
 * and reports if the order was successful or not.
 */
public class Retailer implements Runnable
{
  private String url;
  private String user;
  private String password;

  public Retailer(String url, String user, String password)
  {
    this.url = url;
    this.user = user;
    this.password = password;
  }

  public void run()
  {
    ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(user, password, url);
    try
    {
      Connection connection = connectionFactory.createConnection();

      // The Retailer's session is non-trasacted.
      Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
      Destination vendorOrderQueue = session.createQueue("VendorOrderQueue");
      TemporaryQueue retailerConfirmQueue = session.createTemporaryQueue();

      MessageProducer producer = session.createProducer(vendorOrderQueue);
      MessageConsumer replyConsumer = session.createConsumer(retailerConfirmQueue);

      connection.start();

      for (int i = 0; i < 5; i++)
      {
        //System.out.println("預定: " + i);
        
        MapMessage message = session.createMapMessage();
        message.setString("Item", "Computer(s)");
        int quantity = (int) (Math.random() * 4) + 1;
        message.setInt("Quantity", quantity);
        message.setJMSReplyTo(retailerConfirmQueue);
        producer.send(message);
        System.out.println("Retailer: Ordered " + quantity + " computers.");

        MapMessage reply = (MapMessage) replyConsumer.receive();
        if (reply.getBoolean("OrderAccepted"))
        {
          System.out.println("Retailer: Order Filled");
        }
        else
        {
          System.out.println("Retailer: Order Not Filled");
        }
      }

      // Send a non-MapMessage to signal the end
      producer.send(session.createMessage());

      replyConsumer.close();
      connection.close();

    }
    catch (JMSException e)
    {
      e.printStackTrace();
    }
  }

  public static void main(String[] args)
  {
    String url = "tcp://localhost:61616";
    String user = null;
    String password = null;

    if (args.length >= 1)
    {
      url = args[0];
    }

    if (args.length >= 2)
    {
      user = args[1];
    }

    if (args.length >= 3)
    {
      password = args[2];
    }

    Retailer r = new Retailer(url, user, password);

    new Thread(r, "Retailer").start();
  }
}

 

   

package com.jackyin.testamqtran;

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE
 * file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file
 * to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
 * License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by
 * applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
 * governing permissions and limitations under the License.
 */
import java.util.HashMap;
import java.util.Map;
import java.util.Random;

import javax.jms.Connection;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.MapMessage;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageListener;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TemporaryQueue;

import org.apache.activemq.ActiveMQConnectionFactory;

/**
 * The Vendor synchronously, and in a single transaction, receives the
 * order from VendorOrderQueue and sends messages to the two Suppliers via
 * MonitorOrderQueue and StorageOrderQueue.
 * The responses are received asynchronously; when both responses come
 * back, the order confirmation message is sent back to the Retailer.
 */
public class Vendor implements Runnable, MessageListener
{
  private String  url;
  private String  user;
  private String  password;
  private Session asyncSession;
  private int     numSuppliers = 2;
  private Object  supplierLock = new Object();

  public Vendor(String url, String user, String password)
  {
    this.url = url;
    this.user = user;
    this.password = password;
  }

  public void run()
  {
    ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(user, password, url);
    Session session = null;
    Destination orderQueue;
    Destination monitorOrderQueue;
    Destination storageOrderQueue;
    TemporaryQueue vendorConfirmQueue;
    MessageConsumer orderConsumer = null;
    MessageProducer monitorProducer = null;
    MessageProducer storageProducer = null;

    try
    {
      Connection connection = connectionFactory.createConnection();

      session = connection.createSession(true, Session.SESSION_TRANSACTED);
      orderQueue = session.createQueue("VendorOrderQueue");
      monitorOrderQueue = session.createQueue("MonitorOrderQueue");
      storageOrderQueue = session.createQueue("StorageOrderQueue");

      orderConsumer = session.createConsumer(orderQueue);
      monitorProducer = session.createProducer(monitorOrderQueue);
      storageProducer = session.createProducer(storageOrderQueue);

      Connection asyncconnection = connectionFactory.createConnection();
      asyncSession = asyncconnection.createSession(true, Session.SESSION_TRANSACTED);

      vendorConfirmQueue = asyncSession.createTemporaryQueue();
      MessageConsumer confirmConsumer = asyncSession.createConsumer(vendorConfirmQueue);
      confirmConsumer.setMessageListener(this);

      asyncconnection.start();

      connection.start();

      while (true)
      {
        Order order = null;
        try
        {
          Message inMessage = orderConsumer.receive();
          MapMessage message;
          if (inMessage instanceof MapMessage)
          {
            message = (MapMessage) inMessage;

          }
          else
          {
            // end of stream
            Message outMessage = session.createMessage();
            outMessage.setJMSReplyTo(vendorConfirmQueue);
            monitorProducer.send(outMessage);
            storageProducer.send(outMessage);
            session.commit();
            break;
          }

          // Randomly throw an exception in here to simulate a Database error
          // and trigger a rollback of the transaction
          if (new Random().nextInt(3) == 0)
          {
            //throw new JMSException("Simulated Database Error.");
          }

          order = new Order(message);

          MapMessage orderMessage = session.createMapMessage();
          orderMessage.setJMSReplyTo(vendorConfirmQueue);
          orderMessage.setInt("VendorOrderNumber", order.getOrderNumber());
          int quantity = message.getInt("Quantity");
          System.out.println("Vendor: Retailer ordered " + quantity + " " + message.getString("Item"));

          orderMessage.setInt("Quantity", quantity);
          orderMessage.setString("Item", "Monitor");
          monitorProducer.send(orderMessage);
          System.out.println("Vendor: ordered " + quantity + " Monitor(s)");

          orderMessage.setString("Item", "HardDrive");
          storageProducer.send(orderMessage);
          System.out.println("Vendor: ordered " + quantity + " Hard Drive(s)");

          session.commit();
          System.out.println("Vendor: Comitted Transaction 1");

        }
        catch (JMSException e)
        {
          System.out.println("Vendor: JMSException Occured: " + e.getMessage());
          e.printStackTrace();
          session.rollback();
          System.out.println("Vendor: Rolled Back Transaction.");
        }
      }

      synchronized (supplierLock)
      {
        while (numSuppliers > 0)
        {
          try
          {
            //System.out.println("wait()之前...");
            supplierLock.wait();
            //System.out.println("wait()之後...");
          }
          catch (InterruptedException e)
          {
            e.printStackTrace();
          }
        }
      }

      connection.close();
      asyncconnection.close();

    }
    catch (JMSException e)
    {
      e.printStackTrace();
    }

  }

  public void onMessage(Message message)
  {
    if (!(message instanceof MapMessage))
    {
      synchronized (supplierLock)
      {
        numSuppliers--;
        supplierLock.notifyAll();
        System.out.println("準備喚醒...");
        
      }
      try
      {
        asyncSession.commit();
        return;
      }
      catch (JMSException e)
      {
        e.printStackTrace();
      }
    }

    int orderNumber = -1;
    try
    {
      MapMessage componentMessage = (MapMessage) message;

      orderNumber = componentMessage.getInt("VendorOrderNumber");
      Order order = Order.getOrder(orderNumber);
      order.processSubOrder(componentMessage);
      asyncSession.commit();

      if (!"Pending".equals(order.getStatus()))
      {
        System.out.println("Vendor: Completed processing for order " + orderNumber);

        MessageProducer replyProducer = asyncSession.createProducer(order.getMessage().getJMSReplyTo());
        MapMessage replyMessage = asyncSession.createMapMessage();
        if ("Fulfilled".equals(order.getStatus()))
        {
          replyMessage.setBoolean("OrderAccepted", true);
          System.out.println("Vendor: sent " + order.quantity + " computer(s)");
        }
        else
        {
          replyMessage.setBoolean("OrderAccepted", false);
          System.out.println("Vendor: unable to send " + order.quantity + " computer(s)");
        }
        replyProducer.send(replyMessage);
        asyncSession.commit();
        System.out.println("Vender: committed transaction 2");
      }
    }
    catch (JMSException e)
    {
      e.printStackTrace();
    }
  }

  public static class Order
  {
    private static Map<Integer, Order> pendingOrders   = new HashMap<Integer, Order>();
    private static int                 nextOrderNumber = 1;

    private int                        orderNumber;
    private int                        quantity;
    private MapMessage                 monitor         = null;
    private MapMessage                 storage         = null;
    private MapMessage                 message;
    private String                     status;

    public Order(MapMessage message)
    {
      this.orderNumber = nextOrderNumber++;
      this.message = message;
      try
      {
        this.quantity = message.getInt("Quantity");
      }
      catch (JMSException e)
      {
        e.printStackTrace();
        this.quantity = 0;
      }
      status = "Pending";
      pendingOrders.put(orderNumber, this);
    }

    public Object getStatus()
    {
      return status;
    }

    public int getOrderNumber()
    {
      return orderNumber;
    }

    public static int getOutstandingOrders()
    {
      return pendingOrders.size();
    }

    public static Order getOrder(int number)
    {
      return pendingOrders.get(number);
    }

    public MapMessage getMessage()
    {
      return message;
    }

    public void processSubOrder(MapMessage message)
    {
      String itemName = null;
      try
      {
        itemName = message.getString("Item");
      }
      catch (JMSException e)
      {
        e.printStackTrace();
      }

      if ("Monitor".equals(itemName))
      {
        monitor = message;
      }
      else if ("HardDrive".equals(itemName))
      {
        storage = message;
      }

      if (null != monitor && null != storage)
      {
        // Received both messages
        try
        {
          if (quantity > monitor.getInt("Quantity"))
          {
            status = "Cancelled";
          }
          else if (quantity > storage.getInt("Quantity"))
          {
            status = "Cancelled";
          }
          else
          {
            status = "Fulfilled";
          }
        }
        catch (JMSException e)
        {
          e.printStackTrace();
          status = "Cancelled";
        }
      }
    }
  }

  public static void main(String[] args)
  {
    String url = "tcp://localhost:61616";
    String user = null;
    String password = null;

    if (args.length >= 1)
    {
      url = args[0];
    }

    if (args.length >= 2)
    {
      user = args[1];
    }

    if (args.length >= 3)
    {
      password = args[2];
    }

    Vendor v = new Vendor(url, user, password);

    new Thread(v, "Vendor").start();
  }
}

 

   

package com.jackyin.testamqtran;

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE
 * file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file
 * to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
 * License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by
 * applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
 * governing permissions and limitations under the License.
 */
import java.util.Random;

import javax.jms.Connection;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.MapMessage;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
import javax.jms.Session;

import org.apache.activemq.ActiveMQConnectionFactory;

/**
 * The Supplier synchronously receives the order from the Vendor and
 * randomly responds with either the number ordered, or some lower
 * quantity. 
 */
public class Supplier implements Runnable
{
  private String       url;
  private String       user;
  private String       password;
  private final String ITEM;
  private final String QUEUE;

  public Supplier(String item, String queue, String url, String user, String password)
  {
    this.url = url;
    this.user = user;
    this.password = password;
    this.ITEM = item;
    this.QUEUE = queue;
  }

  public void run()
  {
    ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(user, password, url);
    Session session = null;
    Destination orderQueue;
    try
    {
      Connection connection = connectionFactory.createConnection();

      session = connection.createSession(true, Session.SESSION_TRANSACTED);
      orderQueue = session.createQueue(QUEUE);
      MessageConsumer consumer = session.createConsumer(orderQueue);

      connection.start();

      while (true)
      {
        Message message = consumer.receive();
        MessageProducer producer = session.createProducer(message.getJMSReplyTo());
        MapMessage orderMessage;
        if (message instanceof MapMessage)
        {
          orderMessage = (MapMessage) message;
        }
        else
        {
          // End of Stream
          producer.send(session.createMessage());
          session.commit();
          producer.close();
          break;
        }

        int quantity = orderMessage.getInt("Quantity");
        System.out.println(ITEM + " Supplier: Vendor ordered " + quantity + " " + orderMessage.getString("Item"));

        MapMessage outMessage = session.createMapMessage();
        outMessage.setInt("VendorOrderNumber", orderMessage.getInt("VendorOrderNumber"));
        outMessage.setString("Item", ITEM);

        quantity = Math
            .min(orderMessage.getInt("Quantity"), new Random().nextInt(orderMessage.getInt("Quantity") * 10));
        outMessage.setInt("Quantity", quantity);

        producer.send(outMessage);
        System.out.println(ITEM + " Supplier: Sent " + quantity + " " + ITEM + "(s)");
        session.commit();
        System.out.println(ITEM + " Supplier: committed transaction");
        producer.close();
      }
      connection.close();
    }
    catch (JMSException e)
    {
      e.printStackTrace();
    }
  }

  public static void main(String[] args)
  {
    String url = "tcp://localhost:61616";
    String user = null;
    String password = null;
    String item = "HardDrive";

    if (args.length >= 1)
    {
      item = args[0];
    }
    String queue;
    if ("HardDrive".equals(item))
    {
      queue = "StorageOrderQueue";
    }
    else if ("Monitor".equals(item))
    {
      queue = "MonitorOrderQueue";
    }
    else
    {
      throw new IllegalArgumentException("Item must be either HardDrive or Monitor");
    }

    if (args.length >= 2)
    {
      url = args[1];
    }

    if (args.length >= 3)
    {
      user = args[2];
    }

    if (args.length >= 4)
    {
      password = args[3];
    }

    Supplier s = new Supplier(item, queue, url, user, password);

    new Thread(s, "Supplier " + item).start();
  }
}

 

package com.jackyin.testamqtran;

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE
 * file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file
 * to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
 * License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by
 * applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
 * governing permissions and limitations under the License.
 */
public class TransactionsDemo
{

  public static void main(String[] args)
  {
    String url = "tcp://localhost:61616";
    String user = null;
    String password = null;

    if (args.length >= 1)
    {
      url = args[0];
    }

    if (args.length >= 2)
    {
      user = args[1];
    }

    if (args.length >= 3)
    {
      password = args[2];
    }

    Retailer r = new Retailer(url, user, password);
    Vendor v = new Vendor(url, user, password);
    Supplier s1 = new Supplier("HardDrive", "StorageOrderQueue", url, user, password);
    Supplier s2 = new Supplier("Monitor", "MonitorOrderQueue", url, user, password);

    new Thread(r, "Retailer").start();
    new Thread(v, "Vendor").start();
    new Thread(s1, "Supplier 1").start();
    new Thread(s2, "Supplier 2").start();
  }

}

 

   

   

   

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章