关于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 "谢谢--                                
代码实例:

  1. package com.xhj.thread;
  2.  
  3. import java.util.Random;
  4.  
  5. /**
  6. * Object类中与线程相关方法的应用
  7. *
  8. * @author XIEHEJUN
  9. *
  10. */
  11. public class ObjectThreadMethod {
  12. /**
  13. * 定义商品最高件数
  14. */
  15. private int count = 10;
  16. /**
  17. * 生产时记录仓库商品件数
  18. */
  19. private int sum = 0;
  20.  
  21. private class Producter implements Runnable {
  22. @Override
  23. public void run() {
  24. for (int i = 0; i < count; i++) {
  25. int num = new Random().nextInt(255);
  26. synchronized (this) {
  27. if (sum == count) {
  28. System.out.println("仓库已满");
  29. try {
  30. this.wait(1000);
  31. } catch (InterruptedException e) {
  32. // TODO Auto-generated catch block
  33. e.printStackTrace();
  34. }
  35. } else {
  36. System.out.println("生产商品" + num + "号");
  37. this.notify();
  38. sum++;
  39. System.out.println("仓库还有商品" + sum + "件");
  40. try {
  41. Thread.sleep(100);
  42. } catch (InterruptedException e) {
  43. // TODO Auto-generated catch block
  44. e.printStackTrace();
  45. }
  46. }
  47. }
  48. }
  49.  
  50. }
  51.  
  52. }
  53.  
  54. private class Consomer implements Runnable {
  55. @Override
  56. public void run() {
  57. for (int i = 0; i < count; i++) {
  58. synchronized (this) {
  59. if (sum == 0) {
  60. System.out.println("仓库已经为空,请补货");
  61. try {
  62. this.wait(1000);
  63. } catch (InterruptedException e) {
  64. // TODO Auto-generated catch block
  65. e.printStackTrace();
  66. }
  67. } else {
  68. System.out.println("消费着买去了一件商品");
  69. this.notify();
  70. sum--;
  71. System.out.println("仓库还有商品" + sum + "件");
  72. try {
  73. Thread.sleep(100);
  74. } catch (InterruptedException e) {
  75. // TODO Auto-generated catch block
  76. e.printStackTrace();
  77. }
  78.  
  79. }
  80. }
  81. }
  82.  
  83. }
  84.  
  85. }
  86.  
  87. /**
  88. * 调用线程服务
  89. */
  90. public void service() {
  91.  
  92. Producter productor = new Producter();
  93. Consomer consomer = new Consomer();
  94. Thread thread1 = new Thread(productor);
  95. Thread thread2 = new Thread(consomer);
  96. thread1.start();
  97. thread2.start();
  98.  
  99. }
  100.  
  101. public static void main(String[] args) {
  102. // TODO Auto-generated method stub
  103. ObjectThreadMethod ob = new ObjectThreadMethod();
  104. ob.service();
  105. }
  106.  
  107. }

注意:  在Object类中,以上所有的方法都是final的,切记勿与Thread类混淆
        且这几个方法要与Synchronized关键字一起使用,他们都是与对象监视器有关的,

当前线程必须拥有此对象的监视器,否则会出现IllegalMonitorStateException异常。

下面将结合一个经典的算法实例来加深我们对于Object中多线程的方法的理解。

经典实例--哲学家进餐问题

有5个哲学家,每个哲学家的右手边有一根筷子,每个哲学家有两种状态,即思考和吃饭。

当哲学家想要吃饭时,必须要保证左右手的筷子都可用,否则哲学家进入等待状态。倘若

5个哲学家都想要吃饭,都处于等待状态,那么此时,线程发生死锁。倘若5个哲学家都不饿,

都在认真思考,那么此时线程进入活锁(即此时都在执行思考的线程,而吃饭的线程则只能等待有人来吃饭)

关系图:

从上图我们可以知道,根据问题描述及关系图,我们首先要建立两个关系类:筷子类--chopsticks哲学家类—Philosopher

为了能更好的将学过的知识融汇贯通并加以运用,在这里我将用内部类的形式完成这两个类之间的联系和调用

通过上面的关系图,我们知道筷子的可用与否,关系着哲学家所处的状态,以及将要执行的进程,因此,筷子的Available要设计成同步的。

另外对于哲学家来说,思考和吃饭是不能同时进行的,两者只能选其一,或者两者皆无法选,只能进入等待,

因此,这两个方法thinking()和eatting()也必须是同步的。

下面是详细的代码实例:

  1. package com.xhj.thread;
  2.  
  3. import java.util.Random;
  4.  
  5. /**
  6. * 哲学家进餐算法(内部类和Object多线程的应用)
  7. *
  8. * @author XIEHEJUN
  9. *
  10. */
  11. public class ChopsiticksAndPhilosophers {
  12.  
  13. /**
  14. * 筷子实体类
  15. *
  16. */
  17. private class Chopstick {
  18. /**
  19. * 筷子编号
  20. */
  21. private int id;
  22. /**
  23. * 筷子是否可用,默认为可用
  24. */
  25. private volatile boolean available = true;
  26.  
  27. public Chopstick(int id) {
  28. this.id = id;
  29. }
  30.  
  31. public int getId() {
  32. return id;
  33. }
  34.  
  35. public void setAvailable(boolean available) {
  36. this.available = available;
  37. }
  38.  
  39. @Override
  40. public String toString() {
  41. // TODO Auto-generated method stub
  42. return id + "号筷子";
  43. }
  44.  
  45. }
  46.  
  47. /**
  48. * 哲学家类
  49. */
  50. private class Philosopyers implements Runnable {
  51. /**
  52. * 哲学家编号
  53. */
  54. private int id;
  55. /**
  56. * 筷子对象数组
  57. */
  58. private Chopstick[] chopsticks;
  59. /**
  60. * 哲学家状态--true表示正在思考;false表示吃饭或者等待吃饭
  61. */
  62. private volatile boolean state;
  63.  
  64. /**
  65. * 获取哲学家左手边的筷子编号
  66. *
  67. * @return
  68. */
  69. private Chopstick getLeftId() {
  70. return chopsticks[id];
  71. }
  72.  
  73. /**
  74. * 获取哲学家右手边的筷子编号
  75. *
  76. * @return
  77. */
  78. private Chopstick getRightId() {
  79. if (id == 0) {
  80. return chopsticks[chopsticks.length - 1];
  81. } else {
  82. return chopsticks[id - 1];
  83. }
  84. }
  85.  
  86. public Philosopyers(int id, Chopstick[] chopsticks) {
  87. this.id = id;
  88. this.chopsticks = chopsticks;
  89. }
  90.  
  91. @Override
  92. public String toString() {
  93. // TODO Auto-generated method stub
  94. return id + "号哲学家";
  95. }
  96.  
  97. /**
  98. * 哲学家正在思考
  99. */
  100. public synchronized void thinking() {
  101. if (state) {
  102. getLeftId().setAvailable(true);
  103. getRightId().setAvailable(true);
  104. System.out.println(id + "号哲学家正在思考");
  105. try {
  106. // 思考1秒的时间
  107. Thread.sleep(1000);
  108. } catch (Exception e) {
  109. e.printStackTrace();
  110. }
  111. }
  112. state = false;
  113. }
  114.  
  115. /**
  116. * 哲学家在吃饭
  117. */
  118. public synchronized void eating() {
  119. if (!state) {
  120. if (getLeftId().available) {
  121. if (getRightId().available) {
  122. getLeftId().available = false;
  123. getRightId().available = false;
  124. System.out.println(id + "号哲学家在吃饭");
  125. try {
  126. // 吃饭吃一秒的时间
  127. Thread.sleep(1000);
  128. } catch (Exception e) {
  129. e.printStackTrace();
  130. }
  131. } else {
  132. System.out.println("左边" + getRightId().getId()
  133. + "号筷子不可用 " + id + "号专家进入等待状态");
  134. try {
  135. wait(new Random().nextInt(100));
  136. } catch (Exception e) {
  137. e.printStackTrace();
  138. }
  139. }
  140. } else {
  141. System.out.println("右边" + getLeftId().getId() + "号筷子不可用 "
  142. + id + "号专家进入等待状态");
  143. try {
  144. wait(new Random().nextInt(100));
  145. } catch (Exception e) {
  146. e.printStackTrace();
  147. }
  148. }
  149. }
  150. state = true;
  151. }
  152.  
  153. @Override
  154. public void run() {
  155. // 执行2次哲学家进餐以便更好的观察其过程(可根据需要修改)
  156. for (int i = 0; i < 2; i++) {
  157. System.out.print(i + "\t");
  158. thinking();
  159. eating();
  160. }
  161. }
  162. }
  163.  
  164. /**
  165. * 哲学家进餐启动服务线程方法
  166. */
  167. public void service() {
  168. Chopstick[] chopsticks = new Chopstick[5];
  169. // 定义筷子数组
  170. for (int id = 0; id < 5; id++) {
  171. chopsticks[id] = new Chopstick(id);
  172. }
  173. // 5个哲学家,启动5个同步线程
  174. for (int id = 0; id < 5; id++) {
  175. Philosopyers phers = new Philosopyers(id, chopsticks);
  176. new Thread(phers).start();
  177. }
  178. }
  179.  
  180. public static void main(String[] args) {
  181. ChopsiticksAndPhilosophers cap = new ChopsiticksAndPhilosophers();
  182. cap.service();
  183. }
  184.  
  185. }

运行结果:

当我们看到这个结果时一定很惊讶,我们应该记得我们仅仅是设定了程序执行两次进餐行为,但是,这里却有三轮“进餐结果”,这又是为什么呢?

其实主要是因为那五位哲学家在第一轮的进餐中,都很累了,所以当要开始第二轮进餐的时候,他们集体跑去吃精神粮食了---思考,使得整个程序进入活锁状态,

即思考的进程一直在执行当中,而吃饭的进程虽然也在运行状态,但是却一直等待有人来吃饭,直到某一位哲学家实在饿得不行从思考中醒来之后,

才真正意义上开始了第二次进餐的行为。

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. 由外边距合并到BFC

    置顶文章:<纯CSS打造银色MacBook Air(完整版)> 上一篇:<JavaScript实现Ajax小结> 作者主页:myvin 博主QQ:851399101(点击QQ和 ...

  2. [wikioi2069]油画(贪心)

    题目:http://www.wikioi.com/problem/2069/ 分析: 首先这个问题比较复杂,涉及到两个重要的考虑点,一个是当前拿来的颜色是否保留,一个是若保留后那么应该把当前盘子的哪个 ...

  3. 转:java多线程--同步容器

    java同步容器 在Java的集合容器框架中,主要有四大类别:List.Set.Queue.Map.List.Set.Queue接口分别继承了Collection接口,Map本身是一个接口.注意Col ...

  4. sql-where

    查询表时不一定每一次都要将表格内的资料都完全抓出.在许多时候,我们会需要选择性地抓资料.就我们的例子来说,我们可能只要抓出营业额超过 $1,000 的资料. 要做到这一点,需要用到 WHERE 这个指 ...

  5. 【SGU 104】Little shop of flowers

    题意 每个花按序号顺序放到窗口,不同窗口可有不同观赏值,所有花都要放上去,求最大观赏值和花的位置. 分析 dp,dp[i][j]表示前i朵花最后一朵在j位置的最大总观赏值. dp[i][j]=max( ...

  6. 【前端学习】sublime开启vim模式

    学习目标:在sublime下开启vim模式,了解基本vim的编辑快捷键. 下载安装Sublime Text 3 :http://www.sublimetext.com/3 Vim/Vi: Vim/Vi ...

  7. POJ1201 Intervals

    Description You are given n closed, integer intervals [ai, bi] and n integers c1, ..., cn. Write a p ...

  8. Code Review Engine Learning

    相关学习资料 https://www.owasp.org/index.php/Code_review https://www.owasp.org/images/8/8e/OWASP_Code_Revi ...

  9. sql server规范

    常见的字段类型选择 1.字符类型建议采用varchar/nvarchar数据类型 2.金额货币建议采用money数据类型 3.科学计数建议采用numeric数据类型 4.自增长标识建议采用bigint ...

  10. ISO 基础之 (十三) protocol 协议

    一 简绍 protocol,简单来说就是一系列不属于任何类的方法列表,其中声明的方法可以被任何类实现.这种模式一般称为代理(delegation)模式.通过Protocol定义各种行为,在不同的场景采 ...