作业:

  有一个水池,水池容量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. lpc1768的rit使用

    LPC1768在系统滴答定时器和通用定时器之外还引入了一个定时器,叫做重复定时器RIT,该定时器只能用于定时操作,带有一个中断,我个人的感觉,这似乎是为了延时函数设计的一个定时器 那么使用该定时器时遵 ...

  2. 饼干是这样压缩的——PHP使用zlib扩展实现页面GZIP压缩输出

    饼干是这样压缩的——PHP使用zlib扩展实现页面GZIP压缩输出 GZIP(GNU-ZIP)是一种压缩技术.经过GZIP压缩后页面大小可以变为原来的30%甚至更小.这样用户浏览的时候就会感觉很爽很愉 ...

  3. BZOJ2318: Spoj4060 game with probability Problem

    #include<iostream> #include<algorithm> #include<cstring> #include<cstdio> #i ...

  4. [Angular Tutorial] 5-Filtering Repeaters

    在上一步中,我们花了很大功夫来布局应用的基础,所以我们现在做点简单点的吧!我们将会添加一个全文本搜索框(没错,这很简单). ·我们的应用现在会有一个搜索框,注意页面中手机列表的改变取决于用户在搜索框键 ...

  5. 【Xilinx-Petalinux学习】-02-建立PetaLinux工程

    前面我已经把PetaLinux成功安装到了Ubuntu虚拟机当中了,接下来就要实际操作,将PetaLinux移植到我们自己的硬件平台当中去. step1:硬件描述文件 有两种PetaLinux工程建立 ...

  6. Android 使用AsyncTask 下载图片的例子,学会使用AsyncTask

    1.添加布局文件:activity_main.xml 1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res ...

  7. hashchange

    <!DOCTYPE html> <html> <head> <title>Hash Change Example</title> <s ...

  8. iOS 专题 之 界面开发 之 控件

    iOS 之 UIViewController iOS 之 Navagation Button iOS 之 UIButton iOS 之 UITextField iOS 之 UIStackView iO ...

  9. 如何使用Grunt(好文)

    Grunt 是什么? Grunt 基于Node.js之上,是一个以任务处理为基础的命令行工具,可以减少优化开发版本为发布版本所需的人力和时间,从而加速开发流程.它的工作原理是把这 些工作整合为不同的任 ...

  10. php正则表达式简介

    正则表达式简介 正则表达式Regular Expression,使用单个字符串来描述.匹配一系列符合某个句法规则的字符串.代表性书籍<正则表达式之道>里面有详细论述,本书籍为个人查阅之用力 ...