java高并发程序设计学习笔记(二)

等待和通知

线程合作中有许许多多的方法,等待wait和通知notify就是其二。还是顾名思义,等待和通知。查阅资料发现wait和notify方法不再thread类中,而是在object对象中。任何方法的都可以去调用这两个方法。A线程调用object.wait(),A线程则会等待,直到其他线程调用这个对象的notify方法。

final static Object obj = new Object();
 public static class t1 extends Thread{
  public void run() {
   synchronized (obj) {
    try {
     System.out.println("Object wait  "+" "+System.currentTimeMillis());
     obj.wait();
    }catch (InterruptedException e) {
     e.printStackTrace();
    }
   }
  }
 }
 public static class t2 extends Thread{
  public void run() {
   synchronized (obj) {
    try {
     obj.notify();
     System.out.println("Object notify"+" "+System.currentTimeMillis());
    } catch (Exception e) {
     e.printStackTrace();
    }
   }
  }
 }
 public static void main(String[] args) throws InterruptedException {
  Thread t1 = new Thread(new t1());
  Thread t2 = new Thread(new t2());
  t1.start();
  Thread.sleep(1000);
  t2.start();
 }

t1线程使object对象执行wait方法,t2线程使object对象执行notify方法。上述代码main方法中的线程执行顺序,先t1等待一秒再t2。在t1线程的同步锁中,wait方法释放当前的锁,让其他等待该锁的线程参与竞争锁的过程,直到某个线程调用的这个锁的notify方法。在调用notify方法时,并不会直接把锁释放了,仅仅只是通知这个对象,等调用notify方法的这线程结束后,可以随机释放一个等待这个对象的锁的队列的其中一个线程,notifyAll是唤醒所有等待这个对象的锁。

挂起和继续执行

public static Object obj = new Object();
 public static class t extends Thread{
  String name;
  t(String name){
   this.name = name;
  }
  public void run() {
   synchronized(obj) {
    System.out.println(name);
    Thread.currentThread().suspend();
   }
  }
 }
 public static void main(String[] args) throws InterruptedException {
  Thread t1 = new t("t1");
  Thread t2 = new t("t2");
  t1.start();
  Thread.sleep(1000);
  t2.start();
  t1.resume();
  t2.resume();
  t1.join();
  t2.join();
 }

suspend和resume同样也是被废弃的方法,当resume方法因为某些原因,在suspend方法执行前执行,那么就会导致线程的永久挂起,所有关于obj对象的锁都会受到牵连。以上代码可以用wait和notify方法代替。

public static Object obj = new Object();
 static boolean k = false;
 static float a = 0;
 public static class t extends Thread{
  String name;
  t(String name){
   this.name = name;
  }
  public void suspendThread() {
   k = true;
  }
  public void resumeThread() {
   k = false;
   synchronized (this) {
    this.notify();
   }
  }
  public void run() {
   synchronized(this) {
    while(k) {
     try {
      wait();
     }catch (Exception e) {
      e.printStackTrace();
     }
    }
    synchronized (obj) {
     for (int i = 0; i < 100; i++) {
      try {
       Thread.sleep(1000);
      } catch (Exception e) {}
      System.out.println(++a);
     }
    }
   }
  }
 }
 public static void main(String[] args) throws InterruptedException {
  t t1 = new t("t1");
  t1.start();
  t1.suspendThread();
  Thread.sleep(5000);
  t1.resumeThread();
 }

还是临时变量k,在t1线程执行后调用挂起线程方法,使得k为true,再等待五秒,执行继续执行方法,使k=false,并通知线程清除挂起标志。也就是线程在执行时遇到死循环,并在循环内执行wait方法,等待5秒后的notify通知并使k=false退出死循环,执行代码。

等待线程结束和谦让

线程的协作,这个就跟我们为人处世很相像了。在程序中,可能会有一个线程等待其他线程全部执行结束自己才执行,或者一个无关紧要的线程把自己“让”给优先级高的线程。于是就有join和yeild这么两个方法。join,它会一直阻塞当前线程,直到这个线程执行结束。或者还有个join(long time)的方法,等待这个线程特定的时间,如果目标线程还在执行,就不等了 ,直接执行。

public class thread extends Thread{
 static int j = 0;
 public static void main(String[] args) throws InterruptedException {
  Thread t = new Thread(new thread());
  t.start();
  //t.join();
  System.out.println(j);
 }
 public void run(){
  for (int i = 0; i < 100000; i++)
   j++;
 }
}

上述代码中,输出结果是0,因为线程还没开始执行就已经把I的值给输出了,如果带上join,则会等待线程t执行结束,这时候输出结果就是100000了。
yiled方法一旦执行,会使这个线程让出cpu时间片,但也会参与资源争夺,由于是完全随机,也有可能让出时间片的下一个点又拿到了时间片。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值