放水

放水

package thread;

import com.sun.org.apache.bcel.internal.generic.IF_ACMPEQ;

import java.util.concurrent.*;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public class MyTestThreadPool extends ThreadPoolExecutor {
    public MyTestThreadPool(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
    }

    public MyTestThreadPool(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory);
    }

    public MyTestThreadPool(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, RejectedExecutionHandler handler) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, handler);
    }

    public MyTestThreadPool(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, handler);
    }


    private final ReentrantLock lock = new ReentrantLock();

    private Condition unpaused = lock.newCondition();

    private boolean isPaused;

    @Override
    protected void beforeExecute(Thread t, Runnable r) {
        super.beforeExecute(t, r);
        lock.lock();
        try {
            while (isPaused) {
                unpaused.await();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }

    }

    public void pause() {
        lock.lock();
        try {
            isPaused = true;
        } finally {
            lock.unlock();
        }
    }

    public void resume() {
        lock.lock();
        try {
            isPaused = false;
            //唤醒
            unpaused.signalAll();
        } finally {
            lock.unlock();
        }
    }

    public static void main(String[] args) throws InterruptedException {
        MyTestThreadPool myTestThreadPool = new MyTestThreadPool(
                10, 20, 10l, TimeUnit.SECONDS, new LinkedBlockingQueue<>()
        );

        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                System.out.println("正在放水");
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };

        System.out.println("开始上班,往水池放1000吨水");
        for (int i = 0; i < 1000; i++) {
            myTestThreadPool.execute(runnable);
        }
        Thread.sleep(2000);
        myTestThreadPool.pause();
        int num = myTestThreadPool.getQueue().size();
        System.out.println("暂停放水");
        System.out.println("中午回家吃饭,暂停放水,还剩" + num + "吨水");
        Thread.sleep(2000);
        myTestThreadPool.resume();
        System.out.println("下午上班,开始放水");
        Thread.sleep(2000);
        myTestThreadPool.shutdown();
        boolean shutdown = myTestThreadPool.isShutdown();
        if (shutdown) {
            System.out.println("五点了开始停水 10后强制停水开始停水");
        }
        boolean awaitTermination = myTestThreadPool.awaitTermination(10, TimeUnit.SECONDS);
        if (awaitTermination) {
            System.out.println("停水成功 水池没水了");

        } else {
                System.out.println("启动强制停水");
                myTestThreadPool.shutdownNow();
            }
        }
    }

请问老师如何计算剩余水的数量 以及我的程序有哪些问题

正在回答 回答被采纳积分+1

登陆购买课程后可参与讨论,去登陆

1回答
好帮手慕小蓝 2022-11-23 18:30:03

同学你好,同学的代码符合题目要求,逻辑清晰,书写规范,做的很棒。

同学代码中已经正确解决了剩余水量的问题,即使用getQueue().size()的方式获取当前队列中剩余任务数的方式。

由于awaitTermination方法并不会立即停止所有任务,所以在shutdownNow()方法前调用getQueue().size()获取剩余水量。修改过的代码如下:

public static void main(String[] args) throws InterruptedException {
	MyTestThreadPool myTestThreadPool = new MyTestThreadPool(10, 20, 10l, TimeUnit.SECONDS,
			new LinkedBlockingQueue<>());

	Runnable runnable = new Runnable() {
		@Override
		public void run() {
			System.out.println("正在放水");
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	};

	System.out.println("开始上班,往水池放1000吨水");
	for (int i = 0; i < 1000; i++) {
		myTestThreadPool.execute(runnable);
	}
	Thread.sleep(200);
	myTestThreadPool.pause();
	int num = myTestThreadPool.getQueue().size();
	System.out.println("暂停放水");
	System.out.println("中午回家吃饭,暂停放水,还剩" + num + "吨水");
	Thread.sleep(200);
	myTestThreadPool.resume();
	System.out.println("下午上班,开始放水");
	Thread.sleep(200);
	//为了防止在获取数量和关闭之间出现的误差,使用同步进行处理
	Object o = new Object();
	synchronized (o) {
		num = myTestThreadPool.getQueue().size();
		myTestThreadPool.shutdown();
		System.out.println("线程池关闭时剩余" + num);
	}
	
	boolean shutdown = myTestThreadPool.isShutdown();
	if (shutdown) {
		System.out.println("五点了开始停水 10后强制停水开始停水");
	}
	boolean awaitTermination = myTestThreadPool.awaitTermination(1, TimeUnit.SECONDS);
	if (awaitTermination) {
		System.out.println("停水成功 水池没水了");

	} else {
		synchronized (o) {
			System.out.println("启动强制停水");
			num = myTestThreadPool.getQueue().size();
			System.out.println("当前剩余" + num);
			myTestThreadPool.shutdownNow();
		}
	}
}

由于同学代码中等待时间过长,无法体现强制关闭,所以需要将awaitTermination中的参数设置小一些。同时由于同学代码中采用抛出的方式,所以需要在异常信息前查看运行结果。运行的效果如下图:

https://img1.sycdn.imooc.com//climg/637df4230921057505930298.jpg

祝学习愉快~

问题已解决,确定采纳
还有疑问,暂不采纳

恭喜解决一个难题,获得1积分~

来为老师/同学的回答评分吧

0 星
请稍等 ...
意见反馈 帮助中心 APP下载
官方微信

在线咨询

领取优惠

免费试听

领取大纲

扫描二维码,添加
你的专属老师