线程的等待和通知机制 线程池的使用

线程的等待和通知一般用的是 wait()和notity方法

wait()让当前线程进入等待状态,直到被通知为止 wait(long)能够设定时间被通知或时间结束

notify()随机通知一个等待的线程 notifyAll()通知所有的等待线程

package com;

public class WaitDemo {

    public void print() throws InterruptedException {
        for (int i=0;i<100;i++){
            System.out.println(Thread.currentThread().getName() + "" + i);
            if (i==50){
                //让线程开始等待
                this.wait();
                System.out.println("线程开始等待");
            }
        }
    }
    public void notifyTest(){
        //让等待的线程开始执行
        this.notifyAll();
    }
    public static void main(String[] args) throws InterruptedException {
        WaitDemo waitDemo = new WaitDemo();
        new Thread(() ->{
          synchronized (waitDemo){
              try {
                  waitDemo.print();
              } catch (InterruptedException e) {
                  e.printStackTrace();
              }
          }
        }).start();
        Thread.sleep(5000);
        synchronized (waitDemo){
            waitDemo.notify();
        }
    }
}

通过notifyAll通知被等待的线程让线程继续执行

wait()和sleep()的区别

wait()来自Object  sleep方法来自Thread

wait()是由锁对象调用  sleep()是由线程调用

wait()执行后会自动释放锁  sleep()执行后不会释放锁

wait执行后可以被通知唤醒也可以设定时间等时间结束

sleep执行后只能等待时间结束后自动唤醒不能通过通知唤醒

生产者消费者模式

某个模块负责产生数据,这些数据由另一个模块来负责处理。产生数据的模块,就形象地称为生产者;而处理数据的模块,就称为消费者。

 生产者消费者模式的优点

  解耦: 利用缓存区让生产者和消费者不直接依赖,降低了耦合性。

  支持并发:生产者和消费者是两个独立的并发体,他们中间是通过缓冲区连接,生产者只需要往缓冲区丢数据,消费者只需要从缓冲区拿数据,这样就能解决因为处理速度的不同而发生阻塞.

  忙闲不均:

当数据制造快的时候,消费者来不及处理,未处理的数据可以暂时存在缓冲区中。 等生产者的制造速度慢下来,消费者再慢慢处理掉,两者都能

  阻塞队列:

 提供了阻塞的入列方法和阻塞的出队方法,如果队列满了就让方法一直处于阻塞状态直到有空间 为止,如果队列空了就让出列方法一直阻塞直到队列有数据可用

BlockingQueue接口

put         添加一个元素                      如果队列满,则阻塞
take        移除并返回队列头部的元素     如果队列为空,则阻塞


public class TestBlockingQueue {
 
    public static void main(String[] args) throws InterruptedException {
 
        ExecutorService service = Executors.newCachedThreadPool();
 
        //初始化一个排队队列,能够容纳10个人
        BlockingQueue<Person> queue = new ArrayBlockingQueue<Person>(10);
        Station station = new Station(queue);
        Texi texi1 = new Texi(queue,"texi1");
        Texi texi2 = new Texi(queue,"texi2");
        Texi texi3 = new Texi(queue,"texi3");
 
        service.execute(station);
        service.execute(texi1);
        service.execute(texi2);
        service.execute(texi3);
 
        Thread.sleep(3000);
        service.shutdownNow();
 
    }
 
    //定义排队的人
    static class Person {
 
        private String name;
 
        public Person(String name) {
            this.name = name;
            System.out.println(name + "被创建");
        }
 
        //上车出发
        public void setOff() {
            System.out.println("Nice,I will set off,I am" + name);
        }
 
        @Override
        public String toString() {
            return "Person{" +
                    "name='" + name + '\'' +
                    '}';
        }
    }
 
    //定义生产者,假定只有一个生产者
    static class Station implements Runnable {
 
        private BlockingQueue<Person> queue;
        volatile static int count = 0;
 
        public Station(BlockingQueue<Person> queue) {
            this.queue = queue;
        }
 
        @Override
        public void run() {
            try {
                while (true) {
 
                    //生产人
                    System.out.println("火车站准备生产人: " + System.currentTimeMillis());
                    Person person = new Person("SB" + count++ + "号");
                    queue.put(person);
                    System.out.println("火车站生产人完毕: " + System.currentTimeMillis());
 
                    //休眠300ms
                    Thread.sleep(300);
                }
            } catch (InterruptedException ex) {
            }
        }
    }
 
    //定义一个消费者
    static class Texi implements Runnable {
 
        private BlockingQueue<Person> queue;
        private String name;
 
        public Texi(BlockingQueue<Person> queue, String s) {
            this.name = s;
            this.queue = queue;
        }
 
        public void run() {
 
            try {
                while (true) {
 
                    //消费乘客
                    System.out.println("消费者" + name + "准备消费乘客: " + System.currentTimeMillis());
 
                    Person person = queue.take();
                    //Yahoo,出发喽!!
                    person.setOff();
 
                    System.out.println("消费者" + name + "消费乘客完毕: " + "|||||||" + System.currentTimeMillis());
 
                    //休眠1000ms,才能接下一个客
                    Thread.sleep(1000);
                }
 
            } catch (InterruptedException ex) {
            }
        }
    }
 

实现类

ArrayBlockingQueue 类 数据结构为数组

LinkedBlockingQueue类 链表结构

线程池:

为什么要使用线程池:线程池能够回收利用线程资源

1:线程和任务分离,提升线程重用性;
2:控制线程并发数量,降低服务器压力,统一管理所有线程;
3:提升系统响应速度,假如创建线程用的时间为T1,执行任务用的时间为T2,销毁线程用的时间为T3,那么使用线程池就免去了T1和T3的时间;

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值