JAVA多线程-线程池-实例模拟上厕所问题

为什么要使用线程池?

启动一个线程是一件很耗资源的事情, 启动线程需要跟底层操作系统打交道,为新线程开辟一个资源空间. 此外,一个进程中,线程过多,会耗尽资源,导致系统崩溃. 所以,重用和控制线程数量,是线程的必要知识.

Executors

J2ME中的java.util.concurrent.Executors就是一个线程执行器工厂,这个执行器可以管理线程池. Executors应该算是一个工厂,使用它类似newInstance的方法,可以创造出各种功能的ExecutorService(interface)实例. ExecutorService是Executor的继承接口.它的实例也就是线程执行器.

下面来看看Executors能产生什么功能的Executor实例.

newFixedThreadPool() - 创造一个管理固定数量线程的线程池.

newCachedThreadPool() - 创造一个管理非固定数量的线程池,线程一旦结束一段时间,则销毁.

newSingleThreadExecutor() - 产生一个单线程的执行器.

newSingleScheduledThreadExecutor() - 产生一个scheduled单线程执行器.

newScheduledThreadPool() - 创造一个scheduled线程的线程池.

有了Executor或者ExecutorService以后,怎么调用线程呢?

用例

一个厕所有3个,人们不停的进厕所做enen的事情.排量随机,蹲坑时间随机.  厕所的容量(capacity)为100, 当厕所的排量(volume)超过容量的时候, 通知清洁工来清洁. 清洁过程中不能再放新人进来. 厕所每天只服务100个人,然后停业.

本例中有4个类:

ThreadPool - main函数入口类.

Toilet - 厕所, 它使用一个具有3个线程处理能力的线程池来表达3个坑(holes)的概念.

People - 人, 排队上厕所

Cleaner - 清洁工, 清扫厕所

package concurrency;

import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ThreadPoolTest {
    
    public static void main(String[] args) {
         new ThreadPoolTest().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.allowIn(p);
        }
    }
    
    private class Toilet {
        private volatile boolean cleaning = false;
        private volatile int volume=0;
        private final int CAPACITY = 100;
        private volatile int peopleIn = 0;
        private volatile int count = 0;
        private Cleaner cleaner;
        // 3 holes in his toilet.
        private ExecutorService holes = Executors.newFixedThreadPool(3);
        
        private Toilet() {
            this.cleaner = new Cleaner(this);
        }
        private synchronized boolean allowIn(Runnable people) {
            // If toilet is cleaning or 3 holes are taken, wait.
            while (this.cleaning == true || this.peopleIn >= 3 ) {
                try {
                    this.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            
            // Only serves 100 people one day.
            if (count > 100) {
                this.holes.shutdown();
                return false;
            } else {
                this.peopleIn(((People)people).name);
                holes.submit(people);
                return true;
            }
        }
        
        private synchronized void enEn(String name, int v) {
            this.volume += v;
            System.out.println("People["+name+"] put in ["+v+"]. Toilet volume increases to ["+volume+"]");
            
            // If the volume exceeds capacity, notify cleaner to clean.
            if (this.volume > this.CAPACITY) {
                this.notifyCleaner();
            }
        }

        private void notifyCleaner() {
            if (this.cleaning == false) {
                System.out.println("Toilet volume full with ["+volume+"]. Notify cleaner.");
                holes.submit(cleaner);
            }
        }
        
        private synchronized void peopleIn(String name) {
            System.out.println("People["+name+"] comes in.");
            this.peopleIn ++;
            this.count++;
        }
        
        private synchronized void peopleOut(String name) {
            System.out.println("People["+name+"] comes out.");
            this.peopleIn --;
            this.notifyAll();
        }
        public synchronized void cleaning() {
            this.cleaning = true;
            
        }
        public synchronized void cleaned() {
            this.cleaning = false;
            this.notifyAll();
        }
    }
    
    // One toilet cleaner.
    private class Cleaner implements Runnable {
        private Toilet toilet;
        private Cleaner(Toilet t) {
            this.toilet = t;
        }

        @Override
        public void run() {
            toilet.cleaning();
            System.out.println("Toilet Cleaning...");
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            this.toilet.volume = 0;
            System.out.println("Toilet Clean done.");
            toilet.cleaning = false;
            toilet.cleaned();
        }
    }
    
    private class People implements Runnable {
        private Toilet toilet;
        private String name;
        private People(String name, Toilet t) {
            this.toilet = t;
            this.name = name;
        }

        @Override
        public void run() {
            System.out.println("People["+name+"] is en en en...");
            try {
                Thread.sleep(new Random().nextInt(500));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            
            toilet.enEn(name, new Random().nextInt(11));
            toilet.peopleOut(name);
        }
        
    }

}

转载于:https://my.oschina.net/xpbug/blog/88259

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值