A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© tianhaolin 初级黑马   /  2018-11-21 17:19  /  600 人查看  /  0 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

一、线程池
1.等待唤醒机制
  1)线程间通信
    *通信举例:对产品的状态进行判断
           产品状态(无)-->消费者唤醒生产者线程-->消费者等待-->产品生产完-->修改产品状态为(有)
           产品状态(有)-->生产者唤醒消费者进程-->生产者等待-->产品消耗完-->修改产品状态为(无)
  2)等待唤醒机制--多线程之间的协作机制
    *等待唤醒的方法
           wait();notify();notifyAll;
    *注意事项:
           wait()和notify()必须由同一个锁对象调用
           wait()和notify()必须放在同步代码块中使用
  3)等待唤醒机制需求分析
    *资源类:包子类
          **设置包子的属性
          **设置包子的状态true/false
    *生产者类:线程类
           **设置线程任务:生产包子
           **包子状态true
               包子铺调用wait方法进入等待状态
               包子状态false
               包子铺生产好包子
               修改包子状态为true
               用notify方法唤醒消费者线程
    *消费者类:线程类
           **设置线程任务:消耗包子
             包子状态false
                   吃货线程调用wait方法进入等待状态
                   包子状态true
                   吃货吃包子
                   修改包子状态为false
                   唤醒包子铺做包子


问题:如果有多个顾客,包子铺每次只能生产一个包子,怎么让顾客轮流吃包子???在第三部分解答


2.线程池:降低系统消耗,便于线程管理
  1)原理:创建List<Thread> threads
         使用时:Thread t = threads.remove()
                 使用完毕:threads.add(t)
  2)JDK1.5提供了类和方法,实现线程池
     使用步骤
        *ExecutorService threadPool= Executors.newFixedThreadPool :创建一个固定数量的可重用线程池
        *创建一个类,实现Runnable接口,重写run方法,设置线程任务
                *调用ExecutorService中方法submit,传递线程任务,开启线程,执行run方法
                *调用ExecutorService中方法shutdown销毁线程池(不建议执行)

二、Lambda表达式
1.函数式编程思想:找一个函数来实现功能
  面向对象的思想:找一个对象,调用这个对象,来完成功能
2.Lambda表达式的写法(代替匿名内部类)
  1)Lambda表达式的使用情形-->将一个方法的重写内容传递给一个类
  2)标准格式:
     *(参数列表)->{重写的方法代码}
            注:有返回值的方法在方法体中加入return xxx
     *格式说明:
            ():接口中抽象方法的参数列表,没有参数则为空.有参数就写出参数
            ->:传递参数
            {}:重写接口的抽象方法的方法体
  3)简化格式:
     *可省略的内容
            (参数列表):括号中的数据类型,可以省略不写
            (参数列表):括号中的参数,如果只有一个,那么类型和()都可以省略
            {代码}:如果{}中代码只有一行,无论有无返回值,都可以省略{}和return和;
                  注意事项: {}、return和;要省略必须一起省略;
  4)Lambda表达式的使用限制
     只有函数式接口创建匿名内部实现类的时候才可以使用Lambda表达式
     函数式接口:只有一个抽象方法的接口
         
三、探索分享:使用线程等待实现包子铺的多个顾客轮流吃包子
      主要思想,将顾客加上编号,使用if语句判断是否为自己的号码,如果不是,就进入等待
      另外使用continue语句跳出while循环来实现线程被唤醒后重新判断,而不是继续运行
      1.创建包子类
package cn.itcast.demo01;
[Java] 纯文本查看 复制代码
public class BaoZi {
    private String pi;
    private String xian;
    private boolean exit = false;
    private int index = 0;

    public int getIndex() {
        return index;
    }

    public void setIndex(int index) {
        this.index = index;
    }

    public BaoZi() {
    }

    public BaoZi(String pi, String xian, boolean exit) {
        this.pi = pi;
        this.xian = xian;
        this.exit = exit;
    }

    public String getPi() {
        return pi;
    }

    public void setPi(String pi) {
        this.pi = pi;
    }

    public String getXian() {
        return xian;
    }

    public void setXian(String xian) {
        this.xian = xian;
    }

    public boolean isExit() {
        return exit;
    }


    public void setExit(boolean exit) {
        this.exit = exit;
    }
}
  2.创建包子铺线程类
[Java] 纯文本查看 复制代码
package cn.itcast.demo01;

public class BaoZiPu implements Runnable {
    private BaoZi bz;
    private int number;

    public BaoZiPu() {
    }

    public BaoZiPu(BaoZi bz,int number) {
        this.bz = bz;
        this.number = number;
    }

    public BaoZi getBz() {
        return bz;
    }

    public void setBz(BaoZi bz) {
        this.bz = bz;
    }

    @Override
    public void run() {
        int count = 0;
        int index = 0;
        while (true) {
            synchronized (bz) {

                //判断包子的状态是有还是没有,如果有,则进入等待
                if (bz.isExit() == true) {
                    try {
                        bz.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    continue;
                }
                //如果包子的状态是没有,则做包子,做包子需要2秒
                if (count % 2 == 0) {
                    bz.setPi("厚皮");
                    bz.setXian("盐馅");
                } else {
                    bz.setPi("薄皮");
                    bz.setXian("牛肉馅");
                }

                count++;
                bz.setIndex(index);

                if(index< number - 1) index++;
                else index = 0;

                System.out.println("老板开始做" + bz.getPi() + bz.getXian() + "包子");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                //包子做好了,改包子的状态为true
                bz.setExit(true);


                //唤醒顾客线程,吃包子
                bz.notify();
                System.out.println("1个" + bz.getPi() + bz.getXian() + "包子做好了,可以吃了!");
            }
        }

    }
}
  3.创建顾客类
[Java] 纯文本查看 复制代码
package cn.itcast.demo01;

public class Customer implements Runnable {
    private BaoZi bz;
    private String name;
    private int index;

    public Customer() {
    }

    public Customer(String name, int index, BaoZi bz) {
        this.bz = bz;
        this.name = name;
        this.index = index;
    }

    public BaoZi getBz() {
        return bz;
    }

    public void setBz(BaoZi bz) {
        this.bz = bz;
    }

    @Override
    public void run() {
        while (true) {
            synchronized (bz) {
                //查看包子的状态,如果包子没有,则进入等待,则唤醒老板做包子
                if (bz.isExit() == false || bz.getIndex() !=index) {
                    try {
                        bz.notify();
                        bz.wait();//自己进入等待
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    continue;
                }
                //如果有包子,则吃
                System.out.println(name + "正在吃" + bz.getPi() + bz.getXian() + "的包子");

                //吃完了包子
                bz.setExit(false);
                System.out.println("吃完了,请老板继续做包子");
                bz.notify();
                System.out.println("=========================");
            }

        }
    }
}
4.使用测试类测试:
[Java] 纯文本查看 复制代码
package cn.itcast.demo01;

import java.util.LinkedList;
import java.util.List;

public class Test {
    public static void main(String[] args) {
        BaoZi bz = new BaoZi();
        new Thread(new BaoZiPu(bz,5)).start();

        //创建线程池
        LinkedList<Thread> threads = new LinkedList<>(
                List.of(new Thread(new Customer("小A", 0, bz)),
                        new Thread(new Customer("小B", 1, bz)),
                        new Thread(new Customer("小C", 2, bz)),
                        new Thread(new Customer("小D", 3, bz)),
                        new Thread(new Customer("小E", 4, bz))));

        threads.removeFirst().start();
        threads.removeFirst().start();
        threads.removeFirst().start();
        threads.removeFirst().start();
        threads.removeFirst().start();

    }
}

0 个回复

您需要登录后才可以回帖 登录 | 加入黑马