Java POJO: стратегии обработки очереди объектов запроса на сервер

Прямо сейчас я разрываюсь в выборе лучшего способа обработки объектов запросов, которые я отправляю на сервер. Другими словами, у меня есть объекты запроса отслеживания для таких вещей, как отслеживание показов и кликов в моем приложении. Простые запросы с очень низкой полезной нагрузкой. В моем приложении есть места, где указанные объекты, которые необходимо отслеживать, появляются одновременно рядом друг с другом (максимум три одновременных объекта, которые я должен отслеживать), поэтому каждый раз, например, когда указанные объекты видны, я должен создать запрос на отслеживание. объект для каждого из них.

Теперь я уже знаю, что могу легко создать одноэлементный поток очереди, который добавляет эти объекты в вектор, и мой поток либо обрабатывает их в основном цикле, либо вызывает ожидание в очереди, пока у нас не появятся объекты для обработки. Хотя это звучит как четкое решение, очередь может накапливаться в десятки, что иногда может быть громоздким, поскольку для каждого запроса выполняется одно соединение, поэтому она не будет выполняться одновременно.

Я имел в виду создание пула потоков, который позволил бы мне создать два одновременных соединения через семафор и обрабатывать объекты потока, которые будут содержать мои запросы отслеживания событий. Другими словами, я хотел создать функцию, которая создавала бы новый объект потока и добавляла его в вектор, в котором пул потоков перебирал бы набор потоков и обрабатывал бы их по два одновременно. Я знаю, что могу создать функцию, которая будет добавлять такие объекты:

public boolean addThread(Runnable r){
synchronized(_queue){
    while(!dead){
       _queue.addElement(r);
       //TODO: How would I notify my thread pool object to iterate through the list to process the queue? Do I call notify on the queue object, but that would only work on a thread right??
       return true
    }
    return false;
}

Мне интересно, как будут выполняться сами потоки. Как я могу написать функцию, которая будет выполнять пул потоков после добавления потока в список? Кроме того, поскольку семафор будет заблокирован после второго подключения, заблокирует ли это мое приложение до тех пор, пока не появится открытый слот, или он просто заблокируется в объекте пула потоков при циклическом просмотре списка?

Как всегда, поскольку я ориентируюсь на среду J2ME/Blackberry, будут приняты только ответы до версии 1.5, поэтому никаких дженериков или любого класса из пакета Concurrent.

РЕДАКТИРОВАТЬ: Итак, я так понимаю, что это должно выглядеть примерно так:

class MyThreadPool extends Thread{

  private final Vector _queue = new Vector();
  private CappedSemaphore _sem;
  public MyWaitingThread (){
      _sem = new CappedSemaphore(2);
      this.start();
  }
  public void run(){
     while(!dead){
        Runnable r = null;
        synchronized(_queue){
          if(_queue.isEmpty()){
            _queue.wait();
          } else {
            r = _queue.elementAt(0);
            _queue.removeElement(0);
          }
       }
       if(r != null){
          _sem.take();
          r.run();
          _sem.release();
       }
    }
 }
 public boolean addThread(Runnable r){
   synchronized(_queue){
   if(!dead){
     _queue.addElement(r);
     _queue.notifyAll();
     return true
   }
   return false;
 }
}

person Diego Tori    schedule 11.04.2011    source источник
comment
Вы не должны так быстро сбрасывать со счетов пакет параллелизма Java 5. В Java 5 не было ничего волшебного, что позволило бы это сделать, большая часть этого была сделана Дугом Ли в Java 1.4, это было просто стандартизировано в Java 5. backport-jsr166.sourceforge.net/index.php — это бэкпорт j.u.concurrent.   -  person Will Hartung    schedule 12.04.2011
comment
Поскольку реализация Semaphore реализует Serializable (что-то, чего нет в MIDP/CLDC), я не могу просто импортировать класс волей-неволей, поэтому я стремлюсь к решению POJO, что-то, что может быть выполнено на только примитивные и голые объекты.   -  person Diego Tori    schedule 12.04.2011
comment
Все выглядит хорошо с одной мыслью. Если вы гарантируете, что всегда будет запущено два потока, вам не понадобится семафор. Вы ограничиваете параллелизм локальным потоком, поэтому вам не нужно беспокоиться о другом примитиве синхронизации. В противном случае то, что у вас есть, должно работать.   -  person John Vint    schedule 12.04.2011
comment
Мне просто любопытно, как я могу сделать это без использования семафора, поскольку он выглядит так, как он написан, он будет обрабатывать их только последовательно, если я что-то не упустил.   -  person Diego Tori    schedule 12.04.2011


Ответы (1)


Что бы вы хотели сделать, на стороне потока каждый поток ожидает в очереди. Например

class MyWaitingThread extends Thread{

   private final Queue _queue;
   public MyWaitingThread (Queue _queue){
      this._queue = _queue;
   }
   public void run(){
      while(true){
       Runnable r = null;
       synchronized(_queue){
            if(_queue.isEmpty())
                _queue.wait();
            else
               r = queue.pop();
        }
      if(r != null) r.run();
      }
   }
}

И в вашей другой логике это будет выглядеть так:

public void addThread(Runnable r){
     if(!dead){
       synchronized(_queue){
         _queue.addElement(r);
         _queue.notifyAll();
       }
     }
}

Этот _queue.notifyAll разбудит все потоки, ожидающие экземпляра _queue. Кроме того, обратите внимание, что я переместил while(!dead) за пределы синхронизированного блока и изменил его на if(!dead). Я могу представить, что сохранение того, что у вас было изначально, не сработало бы именно так, как вы надеялись.

person John Vint    schedule 11.04.2011
comment
Думаю, я забыл отредактировать функцию, чтобы она возвращала логическое значение, чтобы она могла избежать цикла while, поскольку именно так Sun сделала это для своего простого примера с очередью в учебнике по многопоточности J2ME. Я пойду исправлю это сейчас. Кроме того, я не могу использовать объект Queue, поскольку он не будет работать на J2ME, но я понимаю, что вы подразумеваете. Мне нужно вызвать elementAt, а затем удалитьElement, чтобы я вытащил свой объект из очереди векторов. - person Diego Tori; 12.04.2011