A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 希望的曙光 中级黑马   /  2013-1-3 02:08  /  1341 人查看  /  2 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

wait():使一个线程处于等待状态,并且释放所持有的对象的lock。

sleep():使一个正在运行的线程处于睡眠状态,是一个静态方法,调用此方法要捕捉InterruptedException异常。

notify():唤醒一个处于等待状态的线程,注意的是在调用此方法的时候,并不能确切地唤醒某一个等待状态的线程,而是由JVM确定唤醒哪个线程,而且不是按优先级。

Allnotity():唤醒所有处入等待状态的线程,注意并不是给所有唤醒线程一个对象的锁,而是让它们竞争。

2 个回复

正序浏览
谢谢,但是看得有点晕不是很明白
回复 使用道具 举报
本帖最后由 张会文 于 2013-1-3 07:49 编辑

  对于同步,在具体的Java代码中需要完成一下两个操作:
    把竞争访问的资源标识为private;
    同步哪些修改变量的代码,使用synchronized关键字同步方法或代码。
    当然这不是唯一控制并发安全的途径。
    synchronized关键字使用说明
    synchronized只能标记非抽象的方法,不能标识成员变量。
    为了演示同步方法的使用,构建了一个信用卡账户,起初信用额为100w,然后模拟透支、存款等多个操作。显然银行账户User对象是个竞争资源,而多个并发操作的是账户方法oper(int x),当然应该在此方法上加上同步,并将账户的余额设为私有变量,禁止直接访问。
  1. /**
  2. * Java线程:线程的同步
  3. *
  4. * @author leizhimin 2009-11-4 11:23:32
  5. */
  6. public class Test {
  7.         public static void main(String[] args) {
  8.                 User u = new User("张三", 100);
  9.                 MyThread t1 = new MyThread("线程A", u, 20);
  10.                 MyThread t2 = new MyThread("线程B", u, -60);
  11.                 MyThread t3 = new MyThread("线程C", u, -80);
  12.                 MyThread t4 = new MyThread("线程D", u, -30);
  13.                 MyThread t5 = new MyThread("线程E", u, 32);
  14.                 MyThread t6 = new MyThread("线程F", u, 21);

  15.                 t1.start();
  16.                 t2.start();
  17.                 t3.start();
  18.                 t4.start();
  19.                 t5.start();
  20.                 t6.start();
  21.         }
  22. }

  23. class MyThread extends Thread {
  24.         private User u;
  25.         private int y = 0;

  26.         MyThread(String name, User u, int y) {
  27.                 super(name);
  28.                 this.u = u;
  29.                 this.y = y;
  30.         }

  31.         public void run() {
  32.                 u.oper(y);
  33.         }
  34. }

  35. class User {
  36.         private String code;
  37.         private int cash;

  38.         User(String code, int cash) {
  39.                 this.code = code;
  40.                 this.cash = cash;
  41.         }

  42.         public String getCode() {
  43.                 return code;
  44.         }

  45.         public void setCode(String code) {
  46.                 this.code = code;
  47.         }

  48.         /**
  49.          * 业务方法
  50.          * @param x 添加x万元
  51.          */
  52.         public synchronized void oper(int x) {
  53.                 try {
  54.                         Thread.sleep(10L);
  55.                         this.cash += x;
  56.                         System.out.println(Thread.currentThread().getName() + "运行结束,增加“" + x + "”,当前用户账户余额为:" + cash);
  57.                         Thread.sleep(10L);
  58.                 } catch (InterruptedException e) {
  59.                         e.printStackTrace();
  60.                 }
  61.         }

  62.         @Override
  63.         public String toString() {
  64.                 return "User{" +
  65.                                 "code='" + code + '\'' +
  66.                                 ", cash=" + cash +
  67.                                 '}';
  68.         }
  69. }
复制代码
运行结果:
  1. 线程A运行结束,增加“20”,当前用户账户余额为:120
  2. 线程F运行结束,增加“21”,当前用户账户余额为:141
  3. 线程E运行结束,增加“32”,当前用户账户余额为:173
  4. 线程C运行结束,增加“-80”,当前用户账户余额为:93
  5. 线程B运行结束,增加“-60”,当前用户账户余额为:33
  6. 线程D运行结束,增加“-30”,当前用户账户余额为:3

  7. Process finished with exit code 0

  8. //反面教材,不同步的情况,也就是去掉oper(int x)方法的synchronized修饰符,然后运行程序,结果如下:

  9. 线程A运行结束,增加“20”,当前用户账户余额为:61
  10. 线程D运行结束,增加“-30”,当前用户账户余额为:63
  11. 线程B运行结束,增加“-60”,当前用户账户余额为:3
  12. 线程F运行结束,增加“21”,当前用户账户余额为:61
  13. 线程E运行结束,增加“32”,当前用户账户余额为:93
  14. 线程C运行结束,增加“-80”,当前用户账户余额为:61

  15. Process finished with exit code 0
  16. 很显然,上面的结果是错误的,导致错误的原因是多个线程并发访问了竞争资源u,并对u的属性做了改动  可见同步的重要性。

  17. <div class="blockcode"><blockquote>注意:


  18.     通过前文可知,线程退出同步方法时将释放掉方法所属对象的锁,但还应该注意的是,同步方法中还可以使用特定的方法对线程进行调度。这些方法来自于java.lang.Object类。

  19. void notify()   
  20.                     唤醒在此对象监视器上等待的单个线程。   
  21. void notifyAll()   
  22.                     唤醒在此对象监视器上等待的所有线程。   
  23. void wait()   
  24.                     导致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法。   
  25. void wait(long timeout)   
  26.                     导致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者超过指定的时间量。   
  27. void wait(long timeout, int nanos)   
  28.                     导致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者其他某个线程中断当前线程,或者已超过某个实际时间量。

  29.     结合以上方法,处理多线程同步与互斥问题非常重要,著名的生产者-消费者例子就是一个经典的例子,任何语言多线程必学的例子。
复制代码

评分

参与人数 1技术分 +1 收起 理由
崔政 + 1

查看全部评分

回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马