`
mazhiyuan
  • 浏览: 64270 次
  • 性别: 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
分享到:
评论

相关推荐

    JAVA多线程--信号量(Semaphore)_.docx

    JAVA多线程--信号量(Semaphore) 信号量(Semaphore)是一种多线程环境下的设施,负责协调各个线程,以保证它们能够正确、合理地使用公共资源。从概念上讲,信号量维护了一个许可集。 信号量的类型有两种:单值信号...

    Java中线程同步和线程协作学习笔记

    在Java编程中,线程同步和线程协作是多线程编程的重要概念,确保了在并发环境下程序的正确性和数据的一致性。线程同步的主要目标是解决线程安全问题,即在多线程访问共享资源时避免数据的混乱,保证程序的可再现性。...

    Java抢火车票程序源码-multithread:多线程

    一、Java多线程技术 技术要点 线程的启动 如何使线程暂停 如何使线程停止 线程的优先级 线程安全相关问题 什么是线程 “电脑卡死了,清理一下”大家通常性的做法,这里清理的都是指运行在系统中的进程,如开发的打开...

    java-SE基础学习资料及介绍

    首先,Java SE提供了丰富的类库,包括基础的I/O流、集合框架、多线程、网络编程等模块,这些都是编写Java程序的基础。学习Java SE首先要理解其面向对象的特性,包括封装、继承、多态,以及如何通过类和对象进行程序...

    Java的并发处理方式

    Java 并发处理方式 在多线程编程中,线程之间的并发访问可能...Java 中的并发处理方式是解决多线程编程中并发问题的关键。开发者需要了解 Java 中的锁机制、volatile 变量、原子操作等概念,以便更好地解决并发问题。

    p220- p263哲学家进餐问题 以及 多个线程之间的同步

    "哲学家进餐问题及多线程同步" 在计算机科学中,哲学家进餐问题是一个经典的同步问题。它描述了五个哲学家坐在圆桌旁,每个哲学家都可以拿起左右两边的筷子,但是拿起筷子的顺序不同,可能会导致死锁的情况。 在多...

    Java编程线程间通信与信号量代码示例

    Java编程线程间通信与信号量代码示例有很多应用场景,例如: * 限制并发线程数,避免资源竞争。 * 实现线程间的互斥和同步。 * 解决死锁问题。 Java编程线程间通信与信号量代码示例是Java编程中的一种常见技术,...

    进程与线程的一个简单解释

    进程和线程是计算机系统中执行程序的基本单位,理解它们的概念和运作机制对于进行多线程编程至关重要。这里,我们将深入探讨这两个概念及其关系。 首先,让我们定义一下进程。进程可以被视为一个单独的执行单元,它...

    Java并发相关

    Java并发编程是Java开发中的重要领域,涉及到多线程、资源共享和并发控制等多个知识点。并发问题通常发生在多个线程或进程同时访问共享资源时,可能导致数据不一致、死锁等问题。例如,在银行账户操作的场景中,如果...

    厕所管理艾瑞网群翁群翁群无

    标签中提到的"java"是编程语言,通常涉及的知识点包括但不限于Java语法、面向对象编程、类与对象、异常处理、集合框架、多线程、IO流、网络编程、数据库操作等。 Java是一种广泛使用的高级编程语言,由Sun ...

    java并发问题概述

    Java并发问题概述是指多个进程或线程同时访问同一资源时产生的问题。例如,两个操作员同时操作同一账户,导致账户余额的不确定性。解决这种问题的方法是使用锁,以锁定资源,防止其他线程或进程访问。 在Java中,...

    JVM抽象架构​

    JVM(Java Virtual Machine)是Java程序的运行平台...了解JVM的抽象架构和多线程同步机制对于优化Java应用程序性能和避免并发问题至关重要。开发者需要根据实际需求选择合适的同步策略,以提高程序的并发性和可维护性。

    Java中Semaphore(信号量)的使用方法

    Java中Semaphore(信号量)的使用方法 Semaphore(信号量)是一种非常...Semaphore是一个非常有用的并发访问控制机制,可以用来保护一个或者多个共享资源的访问,解决多个线程并发同一资源造成的数据不一致的问题。

    Java信号量Semaphore

     Semaphore分为单值和多值两种,前者只能被一个线程获得,后者可以被若干个线程获得。  Semaphore实现的功能类似厕所有5个坑,假如有10个人要上厕所,那么同时只能有多少个人去上厕所呢?同时只能有5个人能够...

    AMapPoi:POI搜索工具、地理编码工具

    概述 受启发,使用JavaFX开发高德POI数据获取软件,同时,计划支持GIS常用工具如地理编码、geojson/shp转换等。 ...线程数目:支持多线程爬取,线程数量一般不大于QPS * keys_num * 0.1; 输出格式

Global site tag (gtag.js) - Google Analytics