java笔记--超级类Object多线程的应用+哲学家进餐算法内部类与多线程结合
关于Object类中的线程方法:
Object类是所有Java类的 父类,在该类中定义了三个与线程操作有关的方法,使得所有的Java类在创建之后就支持多线程
这三个方法是:notify(),notifyAll(),wait(),这几个方法都是用来控制线程的运行状态的。
方法列表如下:
notify() : 唤醒在此对象监视器上等待的单个线程
notifyAll() : 唤醒在此对象监视器上等待的所有线程
wait() : 在其他线程时调用此对象的notify()或者notifyAll()方法前,导致当前线程等待
wait(long timeout) : 在notify()或者notifyAll()方法被调用之前或者超过指定的时间之前,导致当前线程等待
wait(long timeout,int nanos) : 在notify()或者notifyAll()方法被调用之前或者超过指定的时间之前,
或者其他线程中断当前线程之前,导致当前线程等待。
--如果朋友您想转载本文章请注明转载地址"http://www.cnblogs.com/XHJT/p/3907610.html "谢谢--
代码实例:
package com.xhj.thread; import java.util.Random; /**
* Object类中与线程相关方法的应用
*
* @author XIEHEJUN
*
*/
public class ObjectThreadMethod {
/**
* 定义商品最高件数
*/
private int count = 10;
/**
* 生产时记录仓库商品件数
*/
private int sum = 0; private class Producter implements Runnable {
@Override
public void run() {
for (int i = 0; i < count; i++) {
int num = new Random().nextInt(255);
synchronized (this) {
if (sum == count) {
System.out.println("仓库已满");
try {
this.wait(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} else {
System.out.println("生产商品" + num + "号");
this.notify();
sum++;
System.out.println("仓库还有商品" + sum + "件");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
} } } private class Consomer implements Runnable {
@Override
public void run() {
for (int i = 0; i < count; i++) {
synchronized (this) {
if (sum == 0) {
System.out.println("仓库已经为空,请补货");
try {
this.wait(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} else {
System.out.println("消费着买去了一件商品");
this.notify();
sum--;
System.out.println("仓库还有商品" + sum + "件");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} }
}
} } } /**
* 调用线程服务
*/
public void service() { Producter productor = new Producter();
Consomer consomer = new Consomer();
Thread thread1 = new Thread(productor);
Thread thread2 = new Thread(consomer);
thread1.start();
thread2.start(); } public static void main(String[] args) {
// TODO Auto-generated method stub
ObjectThreadMethod ob = new ObjectThreadMethod();
ob.service();
} }
注意: 在Object类中,以上所有的方法都是final的,切记勿与Thread类混淆
且这几个方法要与Synchronized关键字一起使用,他们都是与对象监视器有关的,
当前线程必须拥有此对象的监视器,否则会出现IllegalMonitorStateException异常。
下面将结合一个经典的算法实例来加深我们对于Object中多线程的方法的理解。
经典实例--哲学家进餐问题
有5个哲学家,每个哲学家的右手边有一根筷子,每个哲学家有两种状态,即思考和吃饭。
当哲学家想要吃饭时,必须要保证左右手的筷子都可用,否则哲学家进入等待状态。倘若
5个哲学家都想要吃饭,都处于等待状态,那么此时,线程发生死锁。倘若5个哲学家都不饿,
都在认真思考,那么此时线程进入活锁(即此时都在执行思考的线程,而吃饭的线程则只能等待有人来吃饭)
关系图:

从上图我们可以知道,根据问题描述及关系图,我们首先要建立两个关系类:筷子类--chopsticks和哲学家类—Philosopher
为了能更好的将学过的知识融汇贯通并加以运用,在这里我将用内部类的形式完成这两个类之间的联系和调用。
通过上面的关系图,我们知道筷子的可用与否,关系着哲学家所处的状态,以及将要执行的进程,因此,筷子的Available要设计成同步的。
另外对于哲学家来说,思考和吃饭是不能同时进行的,两者只能选其一,或者两者皆无法选,只能进入等待,
因此,这两个方法thinking()和eatting()也必须是同步的。
下面是详细的代码实例:
package com.xhj.thread; import java.util.Random; /**
* 哲学家进餐算法(内部类和Object多线程的应用)
*
* @author XIEHEJUN
*
*/
public class ChopsiticksAndPhilosophers { /**
* 筷子实体类
*
*/
private class Chopstick {
/**
* 筷子编号
*/
private int id;
/**
* 筷子是否可用,默认为可用
*/
private volatile boolean available = true; public Chopstick(int id) {
this.id = id;
} public int getId() {
return id;
} public void setAvailable(boolean available) {
this.available = available;
} @Override
public String toString() {
// TODO Auto-generated method stub
return id + "号筷子";
} } /**
* 哲学家类
*/
private class Philosopyers implements Runnable {
/**
* 哲学家编号
*/
private int id;
/**
* 筷子对象数组
*/
private Chopstick[] chopsticks;
/**
* 哲学家状态--true表示正在思考;false表示吃饭或者等待吃饭
*/
private volatile boolean state; /**
* 获取哲学家左手边的筷子编号
*
* @return
*/
private Chopstick getLeftId() {
return chopsticks[id];
} /**
* 获取哲学家右手边的筷子编号
*
* @return
*/
private Chopstick getRightId() {
if (id == 0) {
return chopsticks[chopsticks.length - 1];
} else {
return chopsticks[id - 1];
}
} public Philosopyers(int id, Chopstick[] chopsticks) {
this.id = id;
this.chopsticks = chopsticks;
} @Override
public String toString() {
// TODO Auto-generated method stub
return id + "号哲学家";
} /**
* 哲学家正在思考
*/
public synchronized void thinking() {
if (state) {
getLeftId().setAvailable(true);
getRightId().setAvailable(true);
System.out.println(id + "号哲学家正在思考");
try {
// 思考1秒的时间
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
}
state = false;
} /**
* 哲学家在吃饭
*/
public synchronized void eating() {
if (!state) {
if (getLeftId().available) {
if (getRightId().available) {
getLeftId().available = false;
getRightId().available = false;
System.out.println(id + "号哲学家在吃饭");
try {
// 吃饭吃一秒的时间
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
} else {
System.out.println("左边" + getRightId().getId()
+ "号筷子不可用 " + id + "号专家进入等待状态");
try {
wait(new Random().nextInt(100));
} catch (Exception e) {
e.printStackTrace();
}
}
} else {
System.out.println("右边" + getLeftId().getId() + "号筷子不可用 "
+ id + "号专家进入等待状态");
try {
wait(new Random().nextInt(100));
} catch (Exception e) {
e.printStackTrace();
}
}
}
state = true;
} @Override
public void run() {
// 执行2次哲学家进餐以便更好的观察其过程(可根据需要修改)
for (int i = 0; i < 2; i++) {
System.out.print(i + "\t");
thinking();
eating();
}
}
} /**
* 哲学家进餐启动服务线程方法
*/
public void service() {
Chopstick[] chopsticks = new Chopstick[5];
// 定义筷子数组
for (int id = 0; id < 5; id++) {
chopsticks[id] = new Chopstick(id);
}
// 5个哲学家,启动5个同步线程
for (int id = 0; id < 5; id++) {
Philosopyers phers = new Philosopyers(id, chopsticks);
new Thread(phers).start();
}
} public static void main(String[] args) {
ChopsiticksAndPhilosophers cap = new ChopsiticksAndPhilosophers();
cap.service();
} }
运行结果:

当我们看到这个结果时一定很惊讶,我们应该记得我们仅仅是设定了程序执行两次进餐行为,但是,这里却有三轮“进餐结果”,这又是为什么呢?
其实主要是因为那五位哲学家在第一轮的进餐中,都很累了,所以当要开始第二轮进餐的时候,他们集体跑去吃精神粮食了---思考,使得整个程序进入活锁状态,
即思考的进程一直在执行当中,而吃饭的进程虽然也在运行状态,但是却一直等待有人来吃饭,直到某一位哲学家实在饿得不行从思考中醒来之后,
才真正意义上开始了第二次进餐的行为。
java笔记--超级类Object多线程的应用+哲学家进餐算法内部类与多线程结合的更多相关文章
- Java笔记---枚举类和注解
Java笔记---枚举类和注解 一.枚举类 自定义枚举类 方式一:JDK5.0之前自定义枚举类 class Seasons { //1. 声明Seasons对象的属性 private final St ...
- Java笔记 #04# 类的初始化顺序补充
参考java中的类的初始化顺序详解 package org.sample; class Bread { Bread() { System.out.println("Bread()" ...
- Java的常用类——Object类、String类
Java的JDK中提供给我们很多封装好的类就是Java API,可以直接调用. Java 的API(API: Application(应用) Programming(程序) Interface(接口) ...
- JAVA笔记7-Object类之toString方法和equals方法
位于rt.jar\java\lang\Object.class Object类是所有Java类的根基类(Java中只有一个根基类,C++中有多个).如果在类声明中未使用extends关键字指明其基类, ...
- Java笔记--常用类
1.String类: --使用Unicode字符编码,一个字符占两个字节: --String类是一个final类,代表不可变的字符序列: --字符串是不可变的,一个字符串对象一旦被配置,其内容是不可变 ...
- JAVA笔记10__Math类、Random类、Arrays类/日期操作类/对象比较器/对象的克隆/二叉树
/** * Math类.Random类.Arrays类:具体查JAVA手册...... */ public class Main { public static void main(String[] ...
- JAVA笔记【类】
java的概述和编程基础在这里我就不过多的强调了,因为已经有学习C和C++的基础了,我在这里强调一下类和对象. [一]类的定义: Java类的定义包括类声明和类体两个部分,其中类体又包含变量声明,方法 ...
- JAVA笔记11__File类/File类作业/字节输出流、输入流/字符输出流、输入流/文件复制/转换流
/** * File类:文件的创建.删除.重命名.得到路径.创建时间等,是唯一与文件本身有关的操作类 */ public class Main { public static void main(St ...
- java笔记--String类格式化当天日期转换符文档
String类格式化当天日期 --如果朋友您想转载本文章请注明转载地址"http://www.cnblogs.com/XHJT/p/3877389.html "谢谢-- 转换符:% ...
随机推荐
- JS闭包文章--(翻译)Callbacks in Loops
原文地址:http://tobyho.com/2011/11/02/callbacks-in-loops/ 某些时候,你需要在循环里创建一个回调函数.我们来试试给页面里每个链接增加点击事件. var ...
- android之SQLlite操作
布局文件 创建了四个按键,分别对应增删改查 <?xml version="1.0" encoding="utf-8"?> <LinearLay ...
- UITableViewdataSourse的协议所有方法
UITableViewDataSource @required- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection ...
- 每天一个linux命令(19):Linux 目录结构
对于每一个Linux学习者来说,了解Linux文件系统的目录结构,是学好Linux的至关重要的一步.,深入了解linux文件目录结构的标准和每个目录的详细功能,对于我们用好linux系统只管重要,下面 ...
- 团队项目作业第二项:利用NABCD模型进行竞争性需求分析
项目需求分析与建议--NABCD模型(王鲁跃负责) N (Need 需求) 对于现在的学生来说,我们认为打字是很重要的.不管在什么方面都需要进行电脑打字,例如文员.QQ.MSN.制作,论文等等,都需要 ...
- 【OpenCV入门教程之一】 安装OpenCV:OpenCV 3.0 +VS 2013 开发环境配置
图片太多,具体过程参照: [OpenCV入门教程之一] 安装OpenCV:OpenCV 3.0.OpenCV 2.4.8.OpenCV 2.4.9 +VS 开发环境配置 说下我这边的设置: 选择deb ...
- 在CentOS上装 ElasticSearch
参考官方文档:Install Elasticsearch with RPM ElasticSearch依赖Java,所以需要先安装Java: 到Oracle官网找到下载链接 http://www.or ...
- BZOJ-1854 游戏 二分图匹配 (并查集)
1854: [Scoi2010]游戏 Time Limit: 5 Sec Memory Limit: 162 MB Submit: 3372 Solved: 1244 [Submit][Status] ...
- BZOJ-1002 轮状病毒 高精度加减+Kirchhoff矩阵数定理+递推
1002: [FJOI2007]轮状病毒 Time Limit: 1 Sec Memory Limit: 162 MB Submit: 3543 Solved: 1953 [Submit][Statu ...
- HDU-1394 Minimum Inversion Number 线段树+逆序对
仍旧在练习线段树中..这道题一开始没有完全理解搞了一上午,感到了自己的shabi.. Minimum Inversion Number Time Limit: 2000/1000 MS (Java/O ...