`
mazhiyuan
  • 浏览: 62656 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

JAVA多线程-厕所问题

阅读更多

在http://my.oschina.net/xpbug/blog/88259上看到的并发问题---上厕所问题,博主使用的是内置锁实现的, 利用空闲时间改为使用可重入锁实现,写的过程充斥着对并发知识的复习,又翻起了Goetz的并发编程实践,真是好书啊。

 

直接上代码了,题目在代码里

 

package org.waitingfortime.并发趣题;

import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * Created by IntelliJ IDEA.
 * User: mazhiyuan
 * Date: 12-11-20
 * Time: 下午5:55
 * 一个厕所有3个坑,人们不停的进厕所做xuxu的事情.排量随机,蹲坑时间随机.
 * 厕所的容量(capacity)为100, 当厕所的排量(volume)超过容量的时候, 通知清洁工来清洁.
 * 清洁过程中不能再放新人进来. 厕所每天只服务100个人,然后停业.
 */
public class ToiletQ1 {
    public static void main(String[] args) {
        new ToiletQ1().test();
    }

    private void test() {
        Toilet toilet = new Toilet();

        boolean allowed = true;
        for (int i = 0; allowed; i++) {
            People p = new People(i + "", toilet);
            allowed = toilet.allow(p);
        }
    }

    class Toilet {
        private volatile AtomicBoolean cleaning = new AtomicBoolean(false);
        private volatile AtomicInteger volume = new AtomicInteger(0);
        private volatile AtomicInteger count = new AtomicInteger(0);
        private volatile AtomicInteger peopleIn = new AtomicInteger(0);
        private final int CAPACITY = 100;
        //3 holes all 
        ExecutorService holes = Executors.newFixedThreadPool(3);
        Lock in = new ReentrantLock();
        Condition yes = in.newCondition();

        Cleaner cleaner;

        public Toilet() {
            this.cleaner = new Cleaner(this);
        }

        boolean allow(Runnable people) {
            in.lock();
            try {
                while (cleaning.get() == true || peopleIn.get() >= 3)
                    try {
                        yes.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                if (count.get() > 100) {
                    holes.shutdown();
                    return false;
                } else {
                    enter(((People) people).name);
                    holes.submit(people);
                    return true;
                }
            } finally {
                in.unlock();
            }
        }

        private void enter(String name) {
            System.out.println("People[" + name + "] comes in.");
            peopleIn.incrementAndGet();
            count.incrementAndGet();
        }

        private void exit(String name) {
            System.out.println("People[" + name + "] comes out.");
            peopleIn.decrementAndGet();
            in.lock();
            try {
                yes.signal();
            } finally {
                in.unlock();
            }
        }

        private void notifyCleaner() {
            if (cleaning.get() == false) {
                clean();
                System.out.println("Toilet volume full with [" + volume.get() + "]. Notify cleaner.");
                holes.submit(cleaner);
            }
        }

        public void xuXu(String name, int i) {
            volume.addAndGet(i);
            System.out.println("People[" + name + "] put in [" + i + "]. Toilet volume increases to [" + volume.get() + "]");
            if (volume.get() >= CAPACITY) {
                notifyCleaner();
            }
        }

        public void clean() {
            cleaning.getAndSet(true);
        }

        public void cleaned() {
            volume.getAndSet(0);
            cleaning.getAndSet(false);
            in.lock();
            try {
                yes.signal();
            } finally {
                in.unlock();
            }
        }
    }

    class People implements Runnable {
        String name;
        Toilet toilet;

        public People(String name, Toilet toilet) {
            this.name = name;
            this.toilet = toilet;
        }

        @Override
        public void run() {
            System.out.println("People[" + name + "] is xu xu xu...");
            try {
                Thread.sleep(new Random().nextInt(100));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            toilet.xuXu(name, new Random().nextInt(11));
            toilet.exit(name);
        }
    }

    class Cleaner implements Runnable {
        private Toilet toilet;

        private Cleaner(Toilet t) {
            this.toilet = t;
        }

        @Override
        public void run() {
//            toilet.clean();
            System.out.println("Toilet Cleaning...");
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("Toilet Clean done.");
            toilet.cleaned();
        }
    }
}
 
0
0
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics