服务器之家

服务器之家 > 正文

java 中线程等待与通知的实现

时间:2021-01-10 11:15     来源/作者:alwyq

java线程等待与通知的实现

前言:

关于等待/通知,要记住的关键点是:

必须从同步环境内调用wait()、notify()、notifyAll()方法。线程不能调用对象上等待或通知的方法,除非它拥有那个对象的锁。

wait()、notify()、notifyAll()都是Object的实例方法。与每个对象具有锁一样,每个对象可以有一个线程列表,他们等待来自该信号(通知)。线程通过执行对象上的wait()方法获得这个等待列表。从那时候起,它不再执行任何其他指令,直到调用对象的notify()方法为止。如果多个线程在同一个对象上等待,则将只选择一个线程(不保证以何种顺序)继续执行。如果没有线程等待,则不采取任何特殊操作。

 示例代码:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package threadwait;
 
public class ThreadA extends Thread{
 
  public int num = 0;
 
  public void run(){
 
    synchronized (this){//在此类对象上实现同步,this指代当前对象
 
      for(int i = 0 ; i < 3 ; ++i)
 
       this.num+=i;
 
      notifyAll();//通知所有在这个对象上等待的线程开始执行,在这里就是通知TestNotify主线程开始执行
 
    }
 
  }
 
  public int getNum(){
 
    return this.num;
 
  }
 
}
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package threadwait;
 
 
 
public class TestNotify{
 
  public static void main(String args[]){
 
    ThreadA threada = new ThreadA();
 
    threada.start();//threada线程有执行的资格,但是还没有开始执行
 
    synchronized(threada){
 
      try{
 
       threada.wait();//主线程等待threada线程执行结束才开始执行
 
       //而且只有获得了当前threada对象的锁之后才能执行wait,就是说在同步域内才可以执行wait,执行wait后放弃对象锁
 
      }catch(InterruptedException e){
 
       e.printStackTrace();
 
      }
 
    }
 
    System.out.println(threada.getNum());
 
  }
 
}

同步可以是在class级别上的,synchronized(A.class),也可以是在对象级别上的synchronized(this),可以是静态同步方法,static synchronized ,静态同步方法是在class级别上的,非静态同步方法是在类对象级别上的,一个类对象只有一个锁,只有获得了该锁才可以对他执行wait操作,后释放掉该锁。

更进一步的实例代码如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
package threadwait;
 
 
 
public class ThreadA extends Thread{
 
  public int num = 0;
 
  public void run(){
 
    synchronized (this){//在此类对象上实现同步,this指代当前对象
 
      for(int i = 0 ; i < 3 ; ++i)
 
       this.num+=i;
 
      try{
 
       Thread.sleep(500);//如果ThreadB的三个示例线程在还没有进入等待状态之前就受到了notifyall的信号
 
       //那将会发生严重后果,因为调用notifyall的线程只可以调用一次notifyall,那造成等待的线程将永远等待下去
 
       //所以在此处让它睡一小会,让其他线程有时间进入等待状态。
 
       //不然会收到
 
      }catch(InterruptedException e){
 
       e.printStackTrace();
 
      }
 
      notifyAll();//通知所有在这个对象上等待的线程开始执行,在这里就是通知TestNotify主线程开始执行
 
    }
 
//   notifyAll();
 
  }
 
  public int getNum(){
 
    return this.num;
 
  }
 
}
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
package threadwait;
 
 
 
public class ThreadB extends Thread{
 
  private ThreadA threada;
 
  public ThreadB(ThreadA ta){
 
    this.threada = ta;
 
  }
 
  public void run(){
 
    System.out.println(Thread.currentThread().getName()+" is waitting.");
 
    synchronized(threada){
 
      try{
 
       threada.wait();
 
      }catch(InterruptedException e){
 
       e.printStackTrace();
 
      }
 
      System.out.println(Thread.currentThread().getName()+" "+this.threada.getNum());
 
    }
 
   
 
  }
 
}
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package threadwait;
 
 
 
public class TestNotify{
 
  public static void main(String args[]){
 
    ThreadA threada = new ThreadA();
 
    new ThreadB(threada).start();
 
    new ThreadB(threada).start();
 
    new ThreadB(threada).start();
 
    threada.start();
 
  }
 
}

如有疑问请留言或者到本站社区交流讨论,感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

原文链接:http://blog.csdn.net/alwyq/article/details/36033719

标签:

相关文章

热门资讯

2020微信伤感网名听哭了 让对方看到心疼的伤感网名大全
2020微信伤感网名听哭了 让对方看到心疼的伤感网名大全 2019-12-26
Intellij idea2020永久破解,亲测可用!!!
Intellij idea2020永久破解,亲测可用!!! 2020-07-29
背刺什么意思 网络词语背刺是什么梗
背刺什么意思 网络词语背刺是什么梗 2020-05-22
歪歪漫画vip账号共享2020_yy漫画免费账号密码共享
歪歪漫画vip账号共享2020_yy漫画免费账号密码共享 2020-04-07
苹果12mini价格表官网报价 iPhone12mini全版本价格汇总
苹果12mini价格表官网报价 iPhone12mini全版本价格汇总 2020-11-13
返回顶部