疯狂java


您现在的位置: 疯狂软件 >> 新闻资讯 >> 正文

浅谈JavaSE线程通信


 

   

  线程通信:

  如果线程A和线程B持有同一个MyObject类的对象object,这两个线程会去调用不同的方法,但是它们是同步执行的,比如:线程B需要等待线程A执行完了methodA()方法之后,它才能执行methodB()方法。这样,线程A和线程B就实现了 通信。

  线程通信中要用到的方法:wait()方法:

  执行同步锁(obj对象)的该方法的线程进入堵塞状态,会释放对象的锁,java虚拟机把该线程放到该对象的等待池中,该线程如果要再次执行,则需要其他线程将它唤醒。

  复制代码

  1 package tongxin;

  2

  3 public class MyThreadA extends Thread {

  4 private Object obj;

  5 public MyThreadA(String name,Object obj){

  6

  7 super(name);

  8 this.obj = obj;

  9

  10 }

  11 public void run(){

  12 synchronized(obj){ //设置obj为同步锁

  13

  14 for(int i = 0;i<10;i++){

  15 System.out.println(Thread.currentThread().getName()+"---"+i);

  16

  17 if(i == 5){

  18 try {

  19 obj.wait();

  20 } catch (InterruptedException e) {

  21 // TODO Auto-generated catch block

  22 e.printStackTrace();

  23 }

  24 try {

  25 sleep(100);

  26 } catch (InterruptedException e) {

  27 // TODO Auto-generated catch block

  28 e.printStackTrace();

  29 }

  30 }

  31 }

  32 }

  33 }

  34

  35 }

  复制代码

  复制代码

  1 package tongxin;

  2

  3 public class Demo01 {

  4

  5 public static void main(String[] args) {

  6 // TODO Auto-generated method stub

  7

  8 Object obj = new Object();

  9 MyThreadA mt1 = new MyThreadA("A",obj);

  10 mt1.start();

  11

  12 }

  13

  14 }

  复制代码

  output:

  1 A---0

  2 A---1

  3 A---2

  4 A---3

  5 A---4

  6 A---5

  当i = 5时,执行了同步锁的wait()方法,然后线程A将同步锁释放进入堵塞状态,如果A线程还有恢复运行,则需要另一个持相同同步锁的线程将其唤醒。

  唤醒线程的方法:notifi()

  另一个线程在运行过程中执行了同步锁的notifi方法, 会唤醒在对象的等待池中等待的一个线程(随机选择),java虚拟机会随机选择一个线程转到对象的锁池中。

  注意一个线程要去唤醒另一个执行了wait()方法进入堵塞状态的线程,则其要去执行同一个同步锁的notifi()方法。

  假如有一个房间,A进去之后把门锁上,A在房间里睡着了,B要把A叫醒,就要用锁(同步锁)上的钥匙把门开开。A与B用的是同一把锁,只不过A是在锁门(wait()方法),B是在开门(notifi()方法)。

  复制代码

  1 package tongxin;

  2

  3 public class MyThreadB extends Thread {

  4 private Object obj;

  5 public MyThreadB(String name,Object obj){

  6

  7 super(name);

  8 this.obj = obj;

  9

  10 }

  11 public void run(){

  12 synchronized(obj){ //设置obj为同步锁

  13

  14 for(int i = 0;i<10;i++){

  15 System.out.println(Thread.currentThread().getName()+"---"+i);

  16

  17 if(i == 2){

  18 obj.notify();

  19 try {

  20 sleep(100);

  21 } catch (InterruptedException e) {

  22 // TODO Auto-generated catch block

  23 e.printStackTrace();

  24 }

  25 }

  26 }

  27 }

  28 }

  29

  30

  31 }

  复制代码

  复制代码

  1 package tongxin;

  2

  3 public class Demo01 {

  4

  5 public static void main(String[] args) {

  6 // TODO Auto-generated method stub

  7

  8 Object obj = new Object();

  9 MyThreadA mt1 = new MyThreadA("A",obj);

  10 MyThreadB mt2 = new MyThreadB("B",obj);

  11 mt1.start();

  12 mt2.start();

  13

  14

  15 }

  16

  17 }

  复制代码

  output:

  复制代码

  A---0

  A---1

  A---2

  A---3

  A---4

  A---5

  B---0

  B---1

  B---2

  B---3

  B---4

  B---5

  B---6

  B---7

  B---8

  B---9

  A---6

  A---7

  A---8

  A---9

  复制代码

  创建一个新的线程对象B来唤醒A线程,运行过程中,i = 2时,B唤醒A线程将其转到对象的锁池中,但此时由于B持有同步锁所以B线程继续运行,运行结束后释放同步锁,此时A获取到同步锁恢复运行。

  notifyAll()方法:

  该方法会唤醒在这个对象锁池中的所有线程。