作业:

  有一个水池,水池容量500L,一边为进水口,一边为出水口,要求进水放水不能同时进行,水池一旦满了不能继续注水,一旦空了,不能继续放水,进水速度5L/s,放水速度2L/s。

  这是我学多线程时做的一道练习题,刚开始对wait()方法存在错误理解导致运行时报异常-----java.lang.IllegalMonitorStateException,修复后,在此把错误写法以及最终正确写法都整理出来。

class Water{

static int litre = 500;

boolean flag=true; //false为可以继续加水,true为可以继续放水

}

class OutPour extends Thread{ //出水类

Water w;

OutPour(Water w){

this.w=w;

}

@Override

public void run() { //正确写法

while(true){

synchronized(w){

if(w.flag==true){ //放水,2L/s

try {

Thread.sleep(60);

} catch (InterruptedException e) {

e.printStackTrace();

}

w.litre=w.litre-2;

System.out.println("放水中,现在还剩"+w.litre+"升水!");

if(w.litre<=0){ //放空了

w.flag=false;

System.out.println("--------空了!--------");

w.notify();

}

}else{

try {

w.wait();//等加满

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

}

}

/*

@Override

public void run() { //错误写法

while(true){

if(w.flag==true){ //放水,2L/s

synchronized(w){

try {

Thread.sleep(60);

} catch (InterruptedException e) {

e.printStackTrace();

}

w.litre=w.litre-2;

System.out.println("放水中,现在还剩"+w.litre+"升水!");

if(w.litre<=0){ //放空了

w.flag=false;

System.out.println("--------空了!--------");

w.notify

}

}

}else{

try {

w.wait();//等加满

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

}

*/

}

class InPour extends Thread{ //进水类

Water w;

InPour(Water w){

this.w=w;

}

@Override

public void run() { //正确写法

while(true){

synchronized(w){

if(w.flag==false){//加水,5L/s

try {

Thread.sleep(60);

} catch (InterruptedException e) {

e.printStackTrace();

}

w.litre=w.litre+5;

System.out.println("加水中,现在有"+w.litre+"升水!");

if(w.litre>=500){//加满了

System.out.println("-------满了!-------");

w.flag=true;

w.notify();

}

}else{

try {

w.wait();

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

}

}

/*

@Override

public void run() { //错误写法

while(true){

if(w.flag==false){ //加水,5L/s

synchronized(w){

try {

Thread.sleep(60);

} catch (InterruptedException e) {

e.printStackTrace();

}

w.litre=w.litre+5;

if(w.litre>=500){ //加满了

System.out.println("-------满了!-------");

w.flag=true;

w.notifyAll();

}

}

}else{

try {

w.wait();

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

}

*/

}

public class Demo11 {

public static void main(String[] args){

Water w = new Water();

OutPour o = new OutPour(w);

InPour i = new InPour(w);

o.start();

i.start();

}

}

  run方法在业务逻辑上并没有错,报异常java.lang.IllegalMonitorStateException,是因为wait()方法必须要放在同步代码块中才能使用。把else{}语句也圈到synchronized代码块即可。也奉劝,先把笔记看了之后再敲代码,能为调试省不少时间。。。

(原创)Java多线程作业题报java.lang.IllegalMonitorStateException解决的更多相关文章

  1. Java多线程编程核心技术---Java多线程技能

    基本概念 进程是操作系统结构的基础,是一次程序的执行,是一个程序及其数据结构在处理机上顺序执行时所发生的活动,是程序在一个数据集合上运行的过程,是系统进行资源分配和调度的独立单位.线程可以理解成是在进 ...

  2. 解决:IDEA unable to import maven project see logs for details问题+java http请求报java.net.SocketException: Permission denied:connect 问题

    背景:用IDEA写了一个java发送http请求的maven项目. 运行时,项目报java.net.SocketException: Permission denied:connect问题: 修改po ...

  3. (1)Java多线程编程核心——Java多线程技能

    1.为什么要使用多线程?多线程的优点? 提高CPU的利用率 2.什么是多线程? 3.Java实现多线程编程的两种方式? a.继承Thread类 public class MyThread01 exte ...

  4. Java多线程编程(1)--Java中的线程

    一.程序.进程和线程   程序是一组指令的有序集合,也可以将其通俗地理解为若干行代码.它本身没有任何运行的含义,它只是一个静态的实体,它可能只是一个单纯的文本文件,也有可能是经过编译之后生成的可执行文 ...

  5. 【java多线程系列】java内存模型与指令重排序

    在多线程编程中,需要处理两个最核心的问题,线程之间如何通信及线程之间如何同步,线程之间通信指的是线程之间通过何种机制交换信息,同步指的是如何控制不同线程之间操作发生的相对顺序.很多读者可能会说这还不简 ...

  6. java 多线程5: java 终止线程及中断机制 (stop()、interrupt() 、interrupted()、isInterrupted())

    JAVA中有3种方式可以终止正在运行的线程 ①线程正常退出,即run()方法执行完毕了 ②使用Thread类中的stop()方法强行终止线程.但stop()方法已经过期了,不推荐使用 ③使用中断机制i ...

  7. java多线程基础(二)--java多线程的基本使用

    java多线程的基本使用 在java中使用多线程,是通过继承Thread这个类或者实现Runnable这个接口或者实现Callable接口来完成多线程的. 下面是很简单的例子代码: package c ...

  8. Java多线程系列一——Java实现线程方法

    Java实现线程的两种方法 继承Thread类 实现Runnable接口 它们之间的区别如下: 1)Java的类为单继承,但可以实现多个接口,因此Runnable可能在某些场景比Thread更适用2) ...

  9. grade配置添加java库导致报 java.lang.RuntimeException: java.lang.RuntimeException: com.android.builder.dexing.DexArchiveMerger

    原因是导入的第三方库中也引入了项目中存在的相同名称的库,导致产生冲突

随机推荐

  1. md5sum校验文件完整性

    1.简介 MD5算法常常被用来验证网络文件传输的完整性,防止文件被人篡改. MD5 全称是报文摘要算法(Message-Digest Algorithm 5),此算法对任意长度的信息逐位进行计算,产生 ...

  2. 现在开始使用 ES6

    ECMAScript已经在2015年6月正式发布了,这门语言一直保持稳定快速的发展而且新功能也在慢慢被现在主流的 JavaScript 引擎所接受.不过要想在浏览器端或者 Node 端直接运行 ES6 ...

  3. UITableView回调和table相关成员方法详解

    http://blog.csdn.net/kingsley_cxz/article/details/9123959 1.UITableView的datasource实现: //回调获取每个sectio ...

  4. Adaptive Server Enterprise ODBC driver connection strings

    Adaptive Server Enterprise 15.0 Driver={Adaptive Server Enterprise};app=myAppName;server=myServerAdd ...

  5. iOS获取设备唯一标识的各种方法?IDFA、IDFV、UDID分别是什么含义?

    一.UDID (Unique Device Identifier) UDID的全称是Unique Device Identifier,顾名思义,它就是苹果IOS设备的唯一识别码,它由40个字符的字母和 ...

  6. linux获得目录下文件个数

    获得当前目录下文件个数赋值给变量panonum: panonum=$(ls -l |grep "^-" | wc -l) 获取指定目录下文件个数赋值给指定变量: panonum=$ ...

  7. iOS调试-LLDB学习总结

    from:http://www.jianshu.com/p/d6a0a5e39b0e LLDB阐述 LLDB 是一个有着 REPL 的特性和 C++ ,Python 插件的开源调试器.LLDB 绑定在 ...

  8. dev中TreeList的应用(转)

    如果需要在单元格添加时则用TreeList如果只是单纯读取数据或检索数据时则用GridControl 1.如果点击添加 时则添加TreeList的节点: protected internal void ...

  9. Zepto.js入门介绍

    GitHub Zepto Zepto的一些可选功能是专门针对移动端浏览器的:因为它的最初目标在移动端提供一个精简的类似jquery的js库. Zepto不支持旧版本的Internet Explorer ...

  10. iOS 之 事件响应者链

    响应者链表示一系列的响应者对象.事件被交由第一个响应者对象处理,如果第一个响应者不处理,事件就沿着响应者链向上传递,交由下一个响应者(Next responder). View->ViewCon ...