等待唤醒机制和线程池

  • 进程间的通信:多个线程在处理同一个资源,但是处理的动作(线程的动作)却不相同。

  • 进程间的通信可以让资源进行有效的利用

  • 等待唤醒中的方法:

  1. wait :让线程进入等待状态
  2. notify :随机唤醒一个线程
  3. notifyAll :唤醒所有线程
  • 注意:等待唤醒中的方法必须要由同一个对象锁调用,而这个对象锁可以是任意对象,因为等待唤醒中的方法来自Object类,而Object类是所有类的父类。而且必须写在同步方法或者同步代码块里面。

  • 下面是包子铺生产包子和顾客买包子的例子

//包子铺
public class baozipu extends Thread{
    private baozi bao;
    public baozipu(baozi bao) {
        this.bao=bao;
    }

    @Override
    public void run() {
        int count = 0;
        while (true) {
            synchronized (this.bao) {
                if (bao.isFlag()) {
                    try {
                        bao.wait();
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }

                }

                if (count % 2 == 0) {
                    bao.setPi("薄皮");
                    bao.setXian("猪肉馅");
                } else {
                    bao.setPi("厚皮");
                    bao.setXian("猪肉馅");
                }
                count++;
                System.out.println("正在生产" + bao.getPi() + bao.getXian() + "包子.....");
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                bao.setFlag(true);
                bao.notify();
                System.out.println("包子做好啦");
            }
        }
    }
}

//包子
public class baozi {
    private String pi;
    private String xian;
    private boolean flag;

    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 isFlag() {
        return flag;
    }

    public void setFlag(boolean flag) {
        this.flag = flag;
    }
}

//顾客
public class guge extends Thread{
    private baozi bao;

    public guge(baozi bao) {
        this.bao = bao;
    }

    @Override
    public void run() {
        while(true){
            synchronized(bao){
                if (bao.isFlag()==false){
                    try {
                        bao.wait();
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
                System.out.println("吃"+bao.getPi()+bao.getXian()+"包子");
                bao.setFlag(false);
                bao.notify();
                System.out.println("吃完了,开始生产包子...");
                System.out.println("--------------------------");
            }
        }
    }
}

//测试
public class Test {
    public static void main(String[] args) {
        baozi bao=new baozi();
        baozipu bzp=new baozipu(bao);
        guge gg=new guge(bao);
        gg.start();
        bzp.start();
    }
}

  • 如果并发的线程数量很多,并且每个线程都是执行一个很短的时间就结束了,这样频繁的创建线程和销毁线程就会大大降低系统的效率,因为创建线程和销毁线程很消耗时间。

  • 我们可以使用java中的线程池来解决这个问题

  • 线程池就是一个容纳多个线程的容器,其中的线程可以反复使用,省去了频繁创建线程的时间,减少了不必要的资源消耗。当程序第一次启动的时候,创建多个线程保存到一个集合中,当我们需要使用的时候,再从集合中remove出来使用,使用remove是因为remove之后线程池中就移除了这个线程,而remove的返回值就是我们remove的线程。

  • 线程池会一直开启,除非手动使用shutdown方法(不建议),某个线程被使用完了之后会自动归还给线程池供其他任务使用。

  • 好处

  1. 降低资源消耗
  2. 提高响应速度
  3. 提高线程的可管理性
  • 线程池的使用步骤
  1. 使用线程池的工厂类Executors里面提供的静态方法类newFixedThreadPool生产一个指定线程数量的线程池

  2. 创建一个实现Runnable接口的类,重写run方法,用于设置线程任务

  3. 调用ExecutorsService中的submit方法,传递线程任务,开启线程

  4. 最后程序结束的时候,可以调用ExecutorsService中的shutdown方法销毁线程池,但是不建议销毁,因为我们创建线程池本来就是为了重复利用里面的线程的

    //Runnable接口的实现类
    public class testimpl implements Runnable{
        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName()+"执行");
        }
    }
    
    //测试类
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    
    public class Test {
        public static void main(String[] args) {
            ExecutorService es= Executors.newFixedThreadPool(2);//创建一个包含两个线程的线程池
            es.submit(new testimpl());
            es.submit(new testimpl());
            es.submit(new testimpl());
            es.submit(new testimpl());
        }
    }
    
    

你可能感兴趣的:(Java学习笔记,java,开发语言)