Java多线程(三)

打印 上一主题 下一主题

主题 1010|帖子 1010|积分 3030

Java多线程(三)


目录

五、线程的通信

5.1 wait() 与 notify() 和 notifyAll() 介绍:


  • wait():令当前线程挂起并放弃CPU、同步资源并等待,使别的线程可访问并修改共享资源,而当前线程排队等候其他线程调用notify() 或 notifyAll() 方法唤醒,唤醒后等待重新获得对监视器的所有权后才能继续执行。
  • notify():唤醒正在排队等待同步资源的线程中优先级最高者结束等待。
  • notifyAll ():唤醒正在排队等待资源的所有线程结束等待。


  • 这三个方法只有在 synchronized 方法 或 synchronized 代码块中才能使用,否则会报 java.lang.IllegalMonitorStateException异常。
  • 因为这三个方法必须有锁对象调用,而任意对象都可以作为 synchronized 的同步锁, 因此这三个方法只能在Object类中声明。
5.2 wait() 的使用:


  • 在当前线程中调用方法: 对象名.wait() 。
  • 使当前线程进入等待(某对象)状态 ,直到另一线程对该对象发出 notify  (或notifyAll) 为止。
  • 调用方法的必要条件:当前线程必须具有对该对象的监控权(加锁)。
  • 调用此方法后,当前线程将释放对象监控权 ,然后进入等待。
  • 在当前线程被 notify 后,要重新获得监控权,然后从断点处继续代码的执行。
5.3 notify() / notifyAll() 的使用


  • 在当前线程中调用方法: 对象名.notify()。
  • 功能:唤醒等待该对象监控权的一个/所有线程。
  • 调用方法的必要条件:当前线程必须具有对该对象的监控权(加锁)。
5.4 经典例题:生产者/消费者问题

题目描述:
生产者(Productor)将产品交给店员(Clerk),而消费者(Customer)从店员处取走产品,店员一次只能持有固定数量的产品(比如:20),如果生产者试图生产更多的产品,店员会叫生产者停一下,如果店中有空位放产品了再通知生产者继续生产;如果店中没有产品了,店员会告诉消费者等一下,如 果店中有产品了再通知消费者来取走产品。
  1. class Clerk{
  2.     private int productCount = 0;
  3.     //生产产品
  4.     public synchronized void produceProduct() {
  5.         if(productCount < 20){
  6.             productCount++;
  7.             System.out.println(Thread.currentThread().getName() + ":开始生产第" + productCount + "个产品");
  8.             
  9.             notify();
  10.         }else{
  11.             //等待
  12.             try {
  13.                 wait();
  14.             } catch (InterruptedException e) {
  15.                 e.printStackTrace();
  16.             }
  17.         }
  18.     }
  19.     //消费产品
  20.     public synchronized void consumeProduct() {
  21.         if(productCount > 0){
  22.             System.out.println(Thread.currentThread().getName() + ":开始消费第" + productCount + "个产品");
  23.             productCount--;
  24.             notify();
  25.         }else{
  26.             //等待
  27.             try {
  28.                 wait();
  29.             } catch (InterruptedException e) {
  30.                 e.printStackTrace();
  31.             }
  32.         }
  33.     }
  34. }
  35. class Producer extends Thread{//生产者
  36.     private Clerk clerk;
  37.     public Producer(Clerk clerk) {
  38.         this.clerk = clerk;
  39.     }
  40.     @Override
  41.     public void run() {
  42.         System.out.println(getName() + ":开始生产产品.....");
  43.         while(true){
  44.             
  45.             try {
  46.                 Thread.sleep(10);
  47.             } catch (InterruptedException e) {
  48.                 e.printStackTrace();
  49.             }
  50.             clerk.produceProduct();
  51.         }
  52.     }
  53. }
  54. class Consumer extends Thread{//消费者
  55.     private Clerk clerk;
  56.     public Consumer(Clerk clerk) {
  57.         this.clerk = clerk;
  58.     }
  59.     @Override
  60.     public void run() {
  61.         System.out.println(getName() + ":开始消费产品.....");
  62.         while(true){
  63.             try {
  64.                 Thread.sleep(20);
  65.             } catch (InterruptedException e) {
  66.                 e.printStackTrace();
  67.             }
  68.             clerk.consumeProduct();
  69.         }
  70.     }
  71. }
  72. public class ProductTest {
  73.     public static void main(String[] args) {
  74.         Clerk clerk = new Clerk();
  75.         Producer p1 = new Producer(clerk);
  76.         p1.setName("生产者1");
  77.         Consumer c1 = new Consumer(clerk);
  78.         c1.setName("消费者1");
  79.         Consumer c2 = new Consumer(clerk);
  80.         c2.setName("消费者2");
  81.         p1.start();
  82.         c1.start();
  83.         c2.start();
  84.     }
  85. }
复制代码
六、JDK5.0新增多线程创建方式

6.1 多线程的创建方式之三:实现Callable接口


  • 创建一个实现 Callable 的实现类
  • 实现call方法,将此线程需要执行的操作声明在call() 中。
  • 创建 Callable 接口实现类的对象。
  • 将此 Callable 接口实现类的对象作为传递到 FutureTask 构造器中,创建 FutureTask 的对象。
  • 将 FutureTask 的对象作为参数传递到 Thread 类的构造器中,创建 Thread 对象,并调用 start() 。
  • 获取 Callable 中 call 方法的返回值。(可选)
[code]//1.创建一个实现Callable的实现类class NumThread implements Callable{    //2.实现call方法,将此线程需要执行的操作声明在call()中    @Override    public Object call() throws Exception {        int sum = 0;        for (int i = 1; i
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

道家人

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表