Хранение данных каждого потока при использовании семафора - PullRequest
0 голосов
/ 11 июня 2010

Моей задачей было решить проблему пяти едящих мыслителей. Каждый из них может есть только 10 раз. Решение должно основываться на семафоре. Я почти решил задачу, и вывод был правильным, когда я просто использовал println для отображения состояния каждого мыслителя. Но есть дополнительная точка для хранения этих состояний в некоторой коллекции. И почему-то я не могу заставить это работать. Теперь мой Вектор хранит только первую итерацию цикла. Что я делаю неправильно ? Вектор статичен, поэтому он должен работать нормально.

import java.util.concurrent.Semaphore;
import java.util.Random;
import java.util.Vector;

public class Thinker extends Thread
{
    private static final Random rand = new Random();
    private static int event=0;
    private int id;
    private Semaphore sem;
    private static Vector<Object[]> vector = new Vector<Object[]>();

    public Thinker(int i, Semaphore s)
    {
        id = i;
        sem = s;
    }

    private void busy()
    {
        try
        {
            sleep(rand.nextInt(1000));
        } catch (InterruptedException e){}
    }

    private void thinking()
    {
        String str = "Thinker " + id + " is thinking";
        vector.add( this.addToObject(System.currentTimeMillis(), event , str) );
        event++;
        busy();
    }

    private void eating()
    {
        String str ="Thinker " + id + " is hungry and is trying to pick up his chopsticks";
        vector.add( this.addToObject(System.currentTimeMillis(), event , str) );
        event++;
        busy();
        str = "Thinker " + id + " is eating";
        vector.add( this.addToObject(System.currentTimeMillis(), event , str) );
        event++;
        busy();
        str = "Thinker" + id + " finished eating, and puts away his chopsticks";
        vector.add( this.addToObject(System.currentTimeMillis(), event , str) );
        event++;
    }

    private Object[] addToObject(long t, int i,String s ){
        Object[] o = new Object[4];
        o[3] = s;
        o[2] = i;
        o[1] = "00000";
        o[0] = t;
        return o;
    }

    @Override
    public void run()
    {
        for (int i = 0; i < 10; ++i)
        {
            thinking();
            try
            {
                sem.acquire();
            } catch (InterruptedException e){}
            eating();
            sem.release();
        }
    }

    public static void main(String[] args)
    {
        final int N = 5;
        Semaphore sem = new Semaphore(N, true);
        Thinker[] thinker = new Thinker[N];

        for (int i = 0; i < N; i++)
        {
            thinker[i] = new Thinker(i, sem);
            thinker[i].start();
        }

        System.out.println("vctr size; "+vector.size());

        for (int i = 0; i < vector.size(); i++) {
            System.out.println();
            Object[] o = vector.get(i);
            System.out.printf("%d %d %s %s\n", o[0], o[2], o[1], o[3]);

        }
    }
}

Вывод, который я должен получить:
1202393057117 1 ООООО «Мыслитель 1 думает»
1202393057117 2 ООООО «Мыслитель 3» думает
1202393057118 3 ООООО Мыслитель 0 думает
1202393057118 4 ООООО «Мыслитель 2» думает
1202393057118 5 ООООО Мыслитель 4 думает
1202393057118 6 OOOOO Thinker 0 голоден и пытается поднять палочки для еды
1202393057119 7 lOOOO Мыслитель 0 ест
1202393057119 8 OOOOO Мыслитель 0 доел
1202393057119 9 ООООО «Мыслитель 0 думает»
1202393057119 10 OOOOO Thinker 0 голоден и пытается поднять палочки для еды
1202393057126 11 lOOOO Мыслитель 0 ест
1202393057126 12 OOOOO Мыслитель 0 доел

Ответы [ 2 ]

0 голосов
/ 11 июня 2010

Дайте мыслителям закончить трапезу, прежде чем пытаться отобразить состояния.

...
/* Start the thinkers... */
for (int i = 0; i < N; i++) {
  thinker[i] = new Thinker(i, sem);
  thinker[i].start();
}
/* Wait for them to finish... */
for (int i = 0; i < N; i++) {
  try {
    thinker[i].join();
  } catch(InterruptedException ex) {
    return;
  }
}
...
0 голосов
/ 11 июня 2010

Ваш основной метод завершается до того, как все / все Потоки сделают свое дело, он не ждет их.

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

В этом конкретном примере вы можете определить:

private static CountDownLatch latch;

В вашем main, создайте его с количеством потоков, которые вы используете:

latch = new CountDownLatch(N);

Перед завершением работы ваших потоков () выполните:

latch.countDown();

Опять же, в вашем основном, прежде чем пытаться напечатать содержимое вектора:

latch.await();

(разбирайтесь с InterruptedException, как считаете нужным).

latch.await() будет блокировать ваш основной поток, пока все остальные потоки не будут завершены, и вы будете записывать свои состояния.

Подробнее: http://java.sun.com/javase/6/docs/api/java/util/concurrent/CountDownLatch.html

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...