Поток не возобновляет выполнение после notify () - PullRequest
0 голосов
/ 13 ноября 2018

У меня есть два класса (Customer и Till).Поток клиента ожидает, пока он не будет уведомлен потоком до.В моей программе поток клиента не выполняет свой код после того, как он был уведомлен потоком обработки.Поток до продолжает выполнение.

Customer.java (поток клиента расширяет поток)

import java.util.concurrent.*;
import java.util.*;

public class Customer extends Thread
{
    Random random_generator = new Random();

    public int minimumQueueLength;
    public Set set;
    public Iterator iterator;
    public boolean placed_in_queue;

    public List<Integer> queue_length_list;
    public CopyOnWriteArrayList till_set = new CopyOnWriteArrayList();
    public Till till, till_to_join;
    public final Object lock;

    public Customer(CopyOnWriteArrayList till_set)
    {
        this.till_set = till_set;
        this.placed_in_queue = false;
        queue_length_list = new ArrayList<Integer>();
        lock = new Object();
    }

    public void run()
    {   
        try 
        {
            place_in_queue();
        } 
        catch (InterruptedException e1)
        {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }

        if(placed_in_queue)
        {   
            synchronized(this.lock)
            {

                System.out.println(this.getName()+" waiting");

                try {
                    this.lock.wait();

                    System.out.println(this.getName()+" has been woken");

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

    public void place_in_queue() throws InterruptedException
    {
        placed_in_queue = false;
        iterator = till_set.iterator();

        while(iterator.hasNext())
        {
            till = (Till)iterator.next();
            queue_length_list.add(till.customer_queue.size());
        } 

        minimumQueueLength = 
                queue_length_list.indexOf(Collections.min(queue_length_list));

        if(minimumQueueLength < 5)
        {
            try 
            {
                till_to_join = (Till)till_set.get(minimumQueueLength);
                till_to_join.customer_queue.put(this);
                placed_in_queue = true;
            } 
            catch (InterruptedException e) 
            {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
}

Till.java (до расширения потокаТема)

import java.util.HashMap;
import java.util.Iterator;
import java.util.Random;
import java.util.concurrent.*;

public class Till extends Thread
{
    BlockingQueue<String> item_queue = new ArrayBlockingQueue<String>(200);
    BlockingQueue<Customer> customer_queue = new ArrayBlockingQueue<Customer>(10);

    public Random random;
    public Customer c;

    public Till(BlockingQueue<String> item_queue) throws InterruptedException
    {
        this.item_queue = item_queue;
        random = new Random();
    }

    public void run()
    {                   
        while(true)
        {   
            try 
            {
                c = customer_queue.take();

                synchronized(c.lock)
                {
                    System.out.println(this.getName()+" Waking up : "+c.getName());
                    c.lock.notify();
                    System.out.println(c.getName()+" has been notified!");
                }           
            } 
            catch (InterruptedException e) 
            {
                e.printStackTrace();
            }
        }
    }
}

CustomerGenerator.java

import java.util.*;
import java.util.concurrent.*;

public class CustomerGenerator extends Thread
{
    public int customer_generation_rate;

    //0 - slow
    //1 - fast

    public Random random_generator;

    public static BlockingQueue<String> item_queue = new ArrayBlockingQueue<String>(200);
    public static CopyOnWriteArrayList till_set = new CopyOnWriteArrayList();

    public int i;

    public CustomerGenerator(int customer_generation_rate, CopyOnWriteArrayList till_set)
    {
        this.customer_generation_rate = customer_generation_rate;
        this.till_set = till_set;
        this.i = 0;
        random_generator = new Random();    
    }

    public void run()
    {
        while(i<1)
        {
            switch(customer_generation_rate)
            {         
            case 0 : try 
            {
                Thread.sleep(random_generator.nextInt(1000));
            } 
            catch (InterruptedException e) 
            {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            break;

            case 1 : try
            {
                Thread.sleep(random_generator.nextInt(500));
            }
            catch(InterruptedException e)
            {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            break;

            default : customer_generation_rate = 0;
            break;
            }

            Customer customer = new Customer(till_set);
            customer.start();
            total_customer_count++;
            i++;
        }
    }
} 

Driver.java

import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Driver
{
    public static BlockingQueue<String> item_queue = new ArrayBlockingQueue<>(200);

    public static CopyOnWriteArrayList<Till> till_set = new CopyOnWriteArrayList<Till>();

    public static Set set;
    public static Iterator iterator;

    public static int i;

    public static final int till_count = 5;

    public static Thread till_thread;

    public static Till till_object;

    public static ExecutorService till_service = Executors.newFixedThreadPool(5);

    public static void main(final String[] args) throws InterruptedException
    {

        for(i=0; i<till_count; i++)
        {
            till_object = new Till(item_queue);
            till_set.add(till_object);
        }

        final CustomerGenerator customer_generator = new CustomerGenerator(0, till_set);
        customer_generator.start();

        Thread.sleep(5000);

        for(final Till t : till_set)
        {
            till_service.submit(t);
        }
    }
}

Полученный результат:

Тема-7 ожидаетНить-1 Просыпается: Нить-7Тема 7 была уведомлена!

Ожидаемый результат:

Thread-7 в ожиданииНить-1 Просыпается: Нить-7Тема 7 была уведомлена!Нить-7 проснулась

Пожалуйста, помогите.Спасибо.:)

Ответы [ 2 ]

0 голосов
/ 15 ноября 2018

CustomerGenerator генерирует одного клиента только при вызове. Создание mcve-версии делает это очень ясным:

//i was initialized: i=0;
public void run()
{
    while(i<1)
    {
        final Customer customer = new Customer(till_set);
        customer.start();
        i++;
    }
}

Я не думаю, что это то, что вы имели в виду.
Я нахожу MCV очень полезной техникой. Мало того, что помогает намного легче, это это мощный инструмент отладки. Во многих случаях при подготовке вы, вероятно, найдете проблему. mcve должен продемонстрировать проблему , а не вашего приложения.

Возможны другие проблемы в коде. Для получения дополнительной помощи, пожалуйста, напишите M Cve.
Некоторые другие комментарии:

В CustomerGenerator вы передаете ссылку всех операций на Customer: final Customer customer = new Customer(till_set);, который позже используется для выбора кассы. Я думаю, что до тех пор, пока вычисление выбора не будет лучше выполнено в другом классе, скажем, TillsManager, в котором может быть стек всех клиентов, ожидающих получения.

В Driver Определение

 public static Till till_object; 
 for(i=0; i<5 ; i++)
 {
    till_object = new Till(item_queue);
    till_set.add(till_object);
 }

означает, что вы получите 5 раз один и тот же объект в till_set. Я полагаю, вы хотели:

 for(i=0; i<till_count; i++)
 {
    Till till_object = new Till(item_queue);
    till_set.add(till_object);
}
0 голосов
/ 13 ноября 2018

Просто подождите до тех пор, пока очередь не получит больше нуля элементов.Из цепочки клиентов после добавления себя в очередь уведомить до.

...