首页 > 开发 > Java > 正文

Java多线程中线程间的通信实例详解

2024-07-13 10:07:21
字体:
来源:转载
供稿:网友

Java多线程中线程间的通信

一、使用while方式来实现线程之间的通信

package com.ietree.multithread.sync;import java.util.ArrayList;import java.util.List;public class MyList {    private volatile static List list = new ArrayList();  public void add() {    list.add("apple");  }  public int size() {    return list.size();  }  public static void main(String[] args) {    final MyList list1 = new MyList();    Thread t1 = new Thread(new Runnable() {      @Override      public void run() {        try {          for (int i = 0; i < 10; i++) {            list1.add();            System.out.println("当前线程:" + Thread.currentThread().getName() + "添加了一个元素..");            Thread.sleep(500);          }        } catch (InterruptedException e) {          e.printStackTrace();        }      }    }, "t1");    Thread t2 = new Thread(new Runnable() {      @Override      public void run() {        while (true) {          if (list1.size() == 5) {            System.out.println("当前线程收到通知:" + Thread.currentThread().getName() + " list size = 5 线程停止..");            throw new RuntimeException();          }        }      }    }, "t2");    t1.start();    t2.start();  }}

程序输出:

当前线程:t1添加了一个元素..当前线程:t1添加了一个元素..当前线程:t1添加了一个元素..当前线程:t1添加了一个元素..当前线程:t1添加了一个元素..Exception in thread "t2" 当前线程收到通知:t2 list size = 5 线程停止..java.lang.RuntimeException  at com.ietree.multithread.sync.MyList$2.run(MyList.java:43)  at java.lang.Thread.run(Unknown Source)当前线程:t1添加了一个元素..当前线程:t1添加了一个元素..当前线程:t1添加了一个元素..当前线程:t1添加了一个元素..当前线程:t1添加了一个元素..

理解:线程Thread2不停地通过while语句检测这个条件(list.size()==5)是否成立 ,从而实现了线程间的通信。但是这种方式会浪费CPU资源。

二、wait notfiy 方法实现多线程中线程之间的通信

使用这种方式实现线程通信需要注意:wait和notify必须配合synchronized关键字使用,wait方法释放锁,notify方法不释放锁。并且在这个例子中必须是Thread2先执行才可以。

package com.ietree.multithread.sync;import java.util.ArrayList;import java.util.List;public class ListAdd3 {  private volatile static List list = new ArrayList();  public void add() {    list.add("apple");  }  public int size() {    return list.size();  }  public static void main(String[] args) {    final ListAdd2 list2 = new ListAdd2();    // 1 实例化出来一个 lock    // 当使用wait 和 notify 的时候 , 一定要配合着synchronized关键字去使用    final Object lock = new Object();    Thread t1 = new Thread(new Runnable() {      @Override      public void run() {        try {          synchronized (lock) {            for (int i = 0; i < 10; i++) {              list2.add();              System.out.println("当前线程:" + Thread.currentThread().getName() + "添加了一个元素..");              Thread.sleep(500);              if (list2.size() == 5) {                System.out.println("已经发出通知..");                //不释放锁,遇到size=5时还是继续执行                lock.notify();              }            }          }        } catch (InterruptedException e) {          e.printStackTrace();        }      }    }, "t1");    Thread t2 = new Thread(new Runnable() {      @Override      public void run() {        synchronized (lock) {          if (list2.size() != 5) {            try {              //释放锁,让其他线程执行              lock.wait();            } catch (InterruptedException e) {              e.printStackTrace();            }          }          System.out.println("当前线程:" + Thread.currentThread().getName() + "收到通知线程停止..");          throw new RuntimeException();        }      }    }, "t2");    t2.start();    t1.start();  }}

程序输出:

当前线程:t1添加了一个元素..当前线程:t1添加了一个元素..当前线程:t1添加了一个元素..当前线程:t1添加了一个元素..当前线程:t1添加了一个元素..已经发出通知..当前线程:t1添加了一个元素..当前线程:t1添加了一个元素..当前线程:t1添加了一个元素..当前线程:t1添加了一个元素..当前线程:t1添加了一个元素..当前线程:t2收到通知线程停止..Exception in thread "t2" java.lang.RuntimeException  at com.ietree.multithread.sync.ListAdd3$2.run(ListAdd3.java:59)  at java.lang.Thread.run(Unknown Source)

三、使用CountDownLatch类来实现多线程中线程之间的实时通信

package com.ietree.multithread.sync;import java.util.ArrayList;import java.util.List;import java.util.concurrent.CountDownLatch;public class ListAdd2 {  private volatile static List list = new ArrayList();  public void add() {    list.add("apple");  }  public int size() {    return list.size();  }  public static void main(String[] args) {    final ListAdd2 list2 = new ListAdd2();    final CountDownLatch countDownLatch = new CountDownLatch(1);    Thread t1 = new Thread(new Runnable() {      @Override      public void run() {        try {          for (int i = 0; i < 10; i++) {            list2.add();            System.out.println("当前线程:" + Thread.currentThread().getName() + "添加了一个元素..");            Thread.sleep(500);            if (list2.size() == 5) {              System.out.println("已经发出通知..");              countDownLatch.countDown();            }          }          // }        } catch (InterruptedException e) {          e.printStackTrace();        }      }    }, "t1");    Thread t2 = new Thread(new Runnable() {      @Override      public void run() {        if (list2.size() != 5) {          try {            countDownLatch.await();          } catch (InterruptedException e) {            e.printStackTrace();          }        }        System.out.println("当前线程:" + Thread.currentThread().getName() + "收到通知线程停止..");        throw new RuntimeException();      }    }, "t2");    t2.start();    t1.start();  }}

程序输出:

当前线程:t1添加了一个元素..当前线程:t1添加了一个元素..当前线程:t1添加了一个元素..当前线程:t1添加了一个元素..当前线程:t1添加了一个元素..已经发出通知..Exception in thread "t2" 当前线程:t1添加了一个元素..当前线程:t2收到通知线程停止..java.lang.RuntimeException  at com.ietree.multithread.sync.ListAdd2$2.run(ListAdd2.java:56)  at java.lang.Thread.run(Unknown Source)当前线程:t1添加了一个元素..当前线程:t1添加了一个元素..当前线程:t1添加了一个元素..当前线程:t1添加了一个元素..

 四、使用多线程模拟一个队列

package com.ietree.multithread.sync;import java.util.LinkedList;import java.util.concurrent.TimeUnit;import java.util.concurrent.atomic.AtomicInteger;public class MyQueue {  // 1、定义一个盛装元素集合  private LinkedList<Object> list = new LinkedList<Object>();  // 2、定义一个计数器  private AtomicInteger count = new AtomicInteger();  // 3、指定上限和下限  private final int minSize = 0;  private final int maxSize;  // 4、构造方法初始化大小  public MyQueue(int size) {    this.maxSize = size;  }  // 5、初始化一个对象用于加锁  private Object lock = new Object();  // put(anObject): 把anObject加到BlockingQueue里,如果BlockQueue没有空间,则调用此方法的线程被阻断,直到BlockingQueue里面有空间再继续.  public void put(Object obj) {    synchronized (lock) {      if (count.get() == this.maxSize) {        try {          lock.wait();        } catch (InterruptedException e) {          e.printStackTrace();        }      }      // 1、加入元素      list.add(obj);      // 2、计数器累加      count.incrementAndGet();      // 3、通知(唤醒)另外一个线程      lock.notify();      System.out.println("新加入的元素为:" + obj);    }  }  // take: 取走BlockingQueue里排在首位的对象,若BlockingQueue为空,阻断进入等待状态直到BlockingQueue有新的数据被加入.  public Object take() {    Object ret = null;    synchronized (lock) {      while (count.get() == this.minSize) {        try {          lock.wait();        } catch (InterruptedException e) {          e.printStackTrace();        }      }      // 1、做移除元素操作      ret = list.removeFirst();      // 2、计数器作递减操作      count.decrementAndGet();      // 3、唤醒另外一个操作      lock.notify();    }    return ret;  }  // 获取长度  public int getSize() {    return this.count.get();  }  public static void main(String[] args) {    final MyQueue mq = new MyQueue(5);    mq.put("a");    mq.put("b");    mq.put("c");    mq.put("d");    mq.put("e");    System.out.println("当前容器的长度:" + mq.getSize());    Thread t1 = new Thread(new Runnable() {      @Override      public void run() {        mq.put("f");        mq.put("g");      }    }, "t1");    t1.start();    Thread t2 = new Thread(new Runnable() {      @Override      public void run() {        Object o1 = mq.take();        System.out.println("移除的元素为:" + o1);        Object o2 = mq.take();        System.out.println("移除的元素为:" + o2);      }    }, "t2");    try {      TimeUnit.SECONDS.sleep(2);    } catch (InterruptedException e) {      e.printStackTrace();    }    t2.start();  }}

程序输出:

新加入的元素为:a新加入的元素为:b新加入的元素为:c新加入的元素为:d新加入的元素为:e当前容器的长度:5移除的元素为:a移除的元素为:b新加入的元素为:f新加入的元素为:g

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!


注:相关教程知识阅读请移步到JAVA教程频道。
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表