关于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多线程的应用+哲学家进餐算法内部类与多线程结合的更多相关文章

  1. Java笔记---枚举类和注解

    Java笔记---枚举类和注解 一.枚举类 自定义枚举类 方式一:JDK5.0之前自定义枚举类 class Seasons { //1. 声明Seasons对象的属性 private final St ...

  2. Java笔记 #04# 类的初始化顺序补充

    参考java中的类的初始化顺序详解 package org.sample; class Bread { Bread() { System.out.println("Bread()" ...

  3. Java的常用类——Object类、String类

    Java的JDK中提供给我们很多封装好的类就是Java API,可以直接调用. Java 的API(API: Application(应用) Programming(程序) Interface(接口) ...

  4. JAVA笔记7-Object类之toString方法和equals方法

    位于rt.jar\java\lang\Object.class Object类是所有Java类的根基类(Java中只有一个根基类,C++中有多个).如果在类声明中未使用extends关键字指明其基类, ...

  5. Java笔记--常用类

    1.String类: --使用Unicode字符编码,一个字符占两个字节: --String类是一个final类,代表不可变的字符序列: --字符串是不可变的,一个字符串对象一旦被配置,其内容是不可变 ...

  6. JAVA笔记10__Math类、Random类、Arrays类/日期操作类/对象比较器/对象的克隆/二叉树

    /** * Math类.Random类.Arrays类:具体查JAVA手册...... */ public class Main { public static void main(String[] ...

  7. JAVA笔记【类】

    java的概述和编程基础在这里我就不过多的强调了,因为已经有学习C和C++的基础了,我在这里强调一下类和对象. [一]类的定义: Java类的定义包括类声明和类体两个部分,其中类体又包含变量声明,方法 ...

  8. JAVA笔记11__File类/File类作业/字节输出流、输入流/字符输出流、输入流/文件复制/转换流

    /** * File类:文件的创建.删除.重命名.得到路径.创建时间等,是唯一与文件本身有关的操作类 */ public class Main { public static void main(St ...

  9. java笔记--String类格式化当天日期转换符文档

    String类格式化当天日期 --如果朋友您想转载本文章请注明转载地址"http://www.cnblogs.com/XHJT/p/3877389.html "谢谢-- 转换符:% ...

随机推荐

  1. PHP PC端接入支付宝和微信感悟

    想着中秋节的时候把异步线程学习完,同事说有个PHP的支付要帮忙做一下,虽然中秋节计划是把C#的异步学完,不过还是喜欢挑战,好久没有像大学一样这么认真的熬夜解决问题了.由于在大学学过asp,它和php有 ...

  2. ASP.NET MVC Controller Session问题

    发现问题 最近在项目中遇到这样一个问题,一直没办法重现,所以几天都没有解决. 测试那边给出的问题是这样的:每天早上来的时候,第一次通过单点登录到系统的时候,总会跳转回登录界面,再次登录就好了.当时给我 ...

  3. Mustache.js前端模板引擎源码解读

    mustache是一个很轻的前端模板引擎,因为之前接手的项目用了这个模板引擎,自己就也继续用了一会觉得还不错,最近项目相对没那么忙,于是就抽了点时间看了一下这个的源码.源码很少,也就只有六百多行,所以 ...

  4. Android数据共享

    Android数据共享 在Android应用程序开发的过程中,借助Bundle类对象来传递数据并不是在所有场景下都适用,就那简单的Intent类对象来说,就不能put进Bundle类对象中.当然不能否 ...

  5. Nodejs学习笔记(七)--- Node.js + Express 构建网站简单示例

    目录 前言 新建项目.建立数据库以及其它准备工作 新建express + ejs 项目:sampleEjs 创建数据库 修改package.json文件,安装session和mysql模块 样式和JQ ...

  6. 每天一个linux命令(51):rcp命令

    rcp代表“remote file copy”(远程文件拷贝).该命令用于在计算机之间拷贝文件.rcp命令有两种格式.第一种格式用于文件到文件的拷贝:第二种格式用于把文件或目录拷贝到另一个目录中. 1 ...

  7. 每天一个linux命令(10):more命令

    more命令,功能类似 cat ,cat命令是整个文件的内容从上到下显示在屏幕上. more会以一页一页的显示方便使用者逐页阅读,而最基本的指令就是按空白键(space)就往下一页显示,按 b 键就会 ...

  8. 事务四大特征:原子性,一致性,隔离性和持久性(ACID)

    一.事务 定义:所谓事务,它是一个操作序列,这些操作要么都执行,要么都不执行,它是一个不可分割的工作单位. 准备工作:为了说明事务的ACID原理,我们使用银行账户及资金管理的案例进行分析. [sql] ...

  9. 【BZOJ 3143】【Hnoi2013】游走 期望+高斯消元

    如果纯模拟,就会死循环,而随着循环每个点的期望会逼近一个值,高斯消元就通过列方正组求出这个值. #include<cstdio> #include<cctype> #inclu ...

  10. text-align:justify_内容居中对齐

    一直发现text-align : justify这个对齐方式不好使,都不知道为什么么么哒: 因为两端对齐的这个行的结束要一个有空字符串或者别的不可见的字符,用户代理会把这个行的最后几个字符往右边拉,实 ...