2016-04-25 5 views
0

Я написал этот код, орудие блокировки очереди:Как сделать объект видимым и редактируемым для всех потоков?

public class MyBlockingQueue extends Thread{ 

final private List <Integer> queue; 

    public MyBlockingQueue(){ 
     queue = new LinkedList<Integer>(); 
    } 

    public synchronized int size() { 

      return queue.size(); 

    } 

    public synchronized void enqueue(int num) 
    throws InterruptedException { 

    this.queue.add(num); 
    System.out.println(getName()+" "+num+" added"); 
    notify(); 
    } 

    public synchronized int dequeue() 
    throws InterruptedException{ 
     while(queue.size() == 0) 
      wait(); 

    return this.queue.remove(0); 
    } 

1.я попытался сделать два потока и заставить их добавить некоторое количество в очереди, а затем удалить его. Unfortunatley, похоже, что у каждой нити есть свой объект. как я могу изменить код, чтобы оба потока обрабатывали один и тот же объект и добавляли/удаляли в ту же очередь блокировки синхронно?

2. Я правильно записываю функцию dequeue (так что, когда один поток удаляет последний номер из очереди, а размер очереди равен нулю, другие потоки будут ждать, пока очередь будет уведомлять их)?

это мой тестер:

public class Main { 
    //checks the blocking queue 
public static void main(String[] args) throws InterruptedException { 
    final MyBlockingQueue mine = new MyBlockingQueue(); 
    Thread t1 = new Thread(){ 
     public void run(){ 
      try { 


       mine.enqueue((int)(Math.random()*1000)); 
       System.out.println(getName()+"<- enter"); 

       } catch (InterruptedException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      }; 
     } 
    }; 

    Thread t2 = new Thread(){ 
     public void run(){ 
      try { 


       mine.dequeue(); 
       System.out.println(getName()+"<-remove"); 

      } catch (InterruptedException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 
     } 
    }; 

    Thread t3 = new Thread(){ 
     public void run(){ 
      try { 


       mine.dequeue(); 
       System.out.println(getName()+"<-remove"); 

      } catch (InterruptedException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 
     } 
    }; 
    Thread t4 = new Thread(){ 
     public void run(){ 
      try { 

       mine.enqueue((int)(Math.random()*1000)); 
       System.out.println(getName()+"<-enter"); 


       } catch (InterruptedException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 
     } 
    }; 
    Thread t5 = new Thread(){ 
     public void run(){ 
      try { 

       mine.dequeue(); 
       System.out.println(getName()+"<-remove"); 


       } catch (InterruptedException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 
     } 
    }; 


    Thread t6 = new Thread(){ 
     public void run(){ 
      System.out.println("thread 6 of entering began, should release last thread of remove"); 
      try { 

       mine.enqueue((int)(Math.random()*1000)); 
       System.out.println(getName()+"<-enter"); 


       } catch (InterruptedException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 
     } 
    }; 
    Thread t7 = new Thread(){ 
     public void run(){ 
      try { 

       mine.dequeue(); 
       System.out.println(getName()+"<-remove"); 


       } catch (InterruptedException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 
     } 
    }; 
    Thread t8 = new Thread(){ 
     public void run(){ 
      try { 

       mine.dequeue(); 
       System.out.println(getName()+"<-remove"); 


       } catch (InterruptedException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 
     } 
    }; 
    Thread t9 = new Thread(){ 
     public void run(){ 
      try { 

       mine.dequeue(); 
       System.out.println(getName()+"<-remove"); 


       } catch (InterruptedException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 
     } 
    }; 
    Thread t10 = new Thread(){ 
     public void run(){ 
      try { 

       mine.dequeue(); 
       System.out.println(getName()+"<-remove"); 


       } catch (InterruptedException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 
     } 
    }; 
    Thread t11 = new Thread(){ 
     public void run(){ 
      System.out.println("thread 11 come to help, this comment before entering, after that we should see one add one remove"); 
      try { 

       mine.enqueue((int)(Math.random()*1000)); 
       System.out.println(getName()+"<-enter"); 


       } catch (InterruptedException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 
     } 
    }; 

    t1.start(); 
    t2.start(); 
    t3.start(); 
    Thread.sleep(5000); 

    t4.start();//will the remove wai for the enter 
    Thread.sleep(5000); 
    /////4 tries to remove, one enter 
    t5.start(); //requesting to remove before have something 
    t7.start(); 
    t8.start(); 
    t9.start(); 
    t10.start(); 
    Thread.sleep(5000); 
    t6.start(); 
    Thread.sleep(20000);//after 20 sec, t11 come to help 
    t11.start(); 

} 

} 

здесь выход:

Thread-0 enqueued 1 
Thread-1<- enter 
Thread-0 dequeued 1 
Thread-2<-remove 
Thread-0 enqueued 4 
Thread-0 dequeued 4 
Thread-3<-remove 
Thread-4<-enter 
thread 6 of entering began, should release last thread of remove 
Thread-0 enqueued 6 
Thread-0 dequeued 6 
Thread-5<-remove 
Thread-6<-enter 
thread 11 come to help, this comment before entering, after that we should see one add one remove 
Thread-0 enqueued 11 
Thread-0 dequeued 11 
Thread-8<-remove 
Thread-11<-enter 
+1

Почему 'расширяет Thread'? Очередь не является ниткой. –

+0

Re: «Кажется, что каждый поток имеет свой собственный объект. Как я могу изменить код, чтобы оба потока обрабатывали один и тот же объект?» Вы не показали нам никакого кода, который использует ваш класс MyBlockingQueue, поэтому трудно сказать, что может или не может быть ошибкой с этим кодом. –

+0

извините, я приложил к нему тестовый код – adi

ответ

0

Вам нужно сделать очередь статическим или передать объект в резьбе при инициализации. Если вы не сделаете этого, эти два потока будут enque/dequeue в отдельных очередях.

+0

, что мне следует включить в static - список или очередь блокировки? – adi

+0

@ Limmen написал точно, что должно быть статической очередью внутри вашего класса MyBlockingQueue – mariusz2108

+0

oh sorry, queue - мой список. Я этого не заметил. Спасибо! – adi

-1

Например:

public class MyBlockingQueue extends Thread { 

    final private static List<Integer> queue = new LinkedList<Integer>(); 

    public synchronized int size() { 

     return MyBlockingQueue.queue.size(); 

    } 

    public synchronized void enqueue(int num) throws InterruptedException { 

     MyBlockingQueue.queue.add(num); 
     System.out.println(getName() + " enqueued " + num); 
     notify(); 
    } 

    public synchronized int dequeue() throws InterruptedException { 
     while (MyBlockingQueue.queue.size() == 0) { 
      wait(); 
     } 
     System.out.println(getName() + " dequeued " + MyBlockingQueue.queue.get(0)); 
     return MyBlockingQueue.queue.remove(0); 
    } 
} 
+0

Я думаю, что я преуспел в управлении им. Иными словами, но спасибо! Кстати, ваш код управляет проблемой, когда «когда один поток удаляет последний номер из очереди, а размер очереди равен нулю, другие потоки будут ждать, пока очередь будет уведомлять их»? – adi

+0

Это не мой, это просто ваш код с рекомендованными выше модификациями. Хорошие и правильные примеры вы можете найти в источнике следующих файлов: ArrayBlockingQueue DelayQueue LinkedBlockingQueue PriorityBlockingQueue SynchronousQueue. В пакете java.util.concurrent –

+0

спасибо за помощь – adi

Смежные вопросы