使用信号量时存储每个线程的数据

时间:2010-06-10 21:13:43

标签: java collections multithreading

我的任务是处理5个吃思想家的问题。他们每人只能吃10次。解决方案应该基于Semaphore。当我简单地使用println显示每个思想家的状态时,我几乎解决了任务和输出是正确的。但还有一点是将这些状态存储在某种集合中。不知怎的,我无法让它发挥作用。现在我的Vector只存储了循环的第一次迭代。我究竟做错了什么 ?矢量是静态的,所以它应该可以正常工作。

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 1OOOO思想家1正在思考 1202393057117 2 OOOOO思想家3正在思考 1202393057118 3OOOO思想家0正在思考 1202393057118 4OOOO思想家2正在思考 1202393057118 5 OOOOO思想家4正在思考 1202393057118 6 OOOOO Thinker 0很饿,正试图拿起他的筷子 1202393057119 7 lOOOO思想家0正在吃着 1202393057119 8 OOOOO思想家0吃完了 1202393057119 9 OOOOO思想家0正在思考 1202393057119 10 OOOOO Thinker 0很饿,正试图拿起他的筷子 1202393057126 11 lOOOO思想家0正在吃香 1202393057126 12 OOOOO Thinker 0吃完了

2 个答案:

答案 0 :(得分:0)

你的主要方法在任何/所有线程执行之前退出,它不会等待它们。

我必须多次处理类似的问题,而且我是CountDownLatch的忠实粉丝。我将举例说明它是如何提供帮助的,而不是说这是唯一/正确的方式。

在此特定示例中,您可以定义:

private static CountDownLatch latch;

在您的主体中,使用您正在使用的线程数来实例化它:

latch = new CountDownLatch(N);

在线程'run()完成之前,执行:

latch.countDown();

再次,在您的主要内容中,在尝试打印矢量的内容之前:

latch.await();

(处理InterruptedException,因为你认为合适)。

latch.await()将阻止你的主线程,直到完成所有其他线程,并且你将记录你的状态。

更多:http://java.sun.com/javase/6/docs/api/java/util/concurrent/CountDownLatch.html

答案 1 :(得分:0)

让思想家在尝试展示各州之前完成他们的用餐。

...
/* 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;
  }
}
...