Java学习笔记10

Java学习笔记10

1.生产消费问题

知识准备


  1. List集合类(接口)—>泛型List<对象>–>List中Integer是int的一个包装类,使其具有一些对象的属性。
  2. 集合里面只能放对象,不能放基本数据类型
  3. List是接口不能创建对象,只能创建一个具体的实现类

    List<Integer> list = new LinkedList<Integer>
    
  4. 特点:长度不固定,想放多少放多少。

  5. 示例代码:

    package Java1;
    
    import java.util.List;
    import java.util.LinkedList;
    
    public class ProductConsumerDemo {
    
        public static void main(String[] args) {
            //创建集合
            List<Integer> list = new LinkedList<Integer>();
            //向集合中添加元素(对象)
            list.add(new Integer(1));
            list.add(new Integer(2));
            list.add(new Integer(3));
            list.add(new Integer(4));
    
            System.out.println(list.size());
    
        }
    
    }
    输出:4
    
  6. 从集合中删除命令–remove

判断集合是否为空的命令–isEmpty()<–始终检查的第一个位置


package Java1;

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

public class ProductConsumerDemo {

    public static void main(String[] args) {
        //创建集合
        List<Integer> list = new LinkedList<Integer>();
        //向集合中添加元素(对象)
        list.add(new Integer(1));
        list.add(new Integer(2));
        list.add(new Integer(3));
        list.add(new Integer(4));

        System.out.println(list.size());
        System.out.println(list.remove(0));
        System.out.println(list.remove(0));
        System.out.println(list.isEmpty());
        System.out.println(list.remove(0));//list.remove(0)会返回一个对象
        System.out.println(list.remove(0));//没删除一个下一个会自动顶到0位置
        //如果继续删则会报错
        System.out.println(list.isEmpty());

    }

}
输出:
4
1
2
false
3
4
true

list+多线程


任务:创建一个list(最大容量为100)和两个线程,一个线程不停的往list里面添加对象,一个线程不停的往外面提取对象

基本示意图:

基本的代码示例–避免栈溢出:

package Java1;

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

public class ProductConsumerDemo {

    public static void main(String[] args) {
        //创建集合
        MyList myList = new MyList();
        Prodctor prodctor =new Prodctor(myList);
        Consumer consumer = new Consumer(myList);

        prodctor.start();
        consumer.start();
    }

}
//生产者
class Prodctor extends Thread{
    private MyList myList;
    public Prodctor(MyList myList) {
        this.myList = myList;
    }
    public void run() {
        int i=1;
        while(true) {
            myList.addList(i);
            i++;
        }
    }
} 
class MyList{
    private int MAX = 20;
    private List<Integer> list =  new LinkedList<Integer>();
    public void addList(int num) {
        while(true) {
            synchronized (list) {
                if (list.size() < MAX) {
                    list.add(new Integer(num));
                    System.out.println("生产者添加的元素数为:"+num);
                    System.out.println("添加后集合的大小为:"+list.size());
                    return;
                }
            }
        }
    }
    public Integer removeList() {
        while(true) {
            synchronized(list) {
                if (list.isEmpty() == false) {
                    int number = list.remove(0);
                    System.out.println("取出后集合的大小为:"+list.size());
                    return number;
                }
            }
        }
    }
}
//消费者
class Consumer extends Thread{
    private MyList myList;
    public Consumer(MyList myList) {
        this.myList = myList;
    }
    public void run() {
        while (true) {
            int num = myList.removeList();
            System.out.println("取出的数据为:"+num);
        }
    }
}
输出:
生产者添加的元素数为:54406
添加后集合的大小为:20
取出后集合的大小为:19
取出的数据为:54387
生产者添加的元素数为:54407
添加后集合的大小为:20
取出后集合的大小为:19
取出的数据为:54388
生产者添加的元素数为:54408
添加后集合的大小为:20
取出后集合的大小为:19
取出的数据为:54389
生产者添加的元素数为:54409
添加后集合的大小为:20
取出后集合的大小为:19
取出的数据为:54390
生产者添加的元素数为:54410

因为存在好多无限循环,所以计算机很忙且资源占用比较多,需要继续改进

分析:生产者发现当list已经满的时候,它不会立即开启下一次循环,而是在本次调用的addlist方法中一直循环,直到再出现list空位置。而我们在代码中的锁就是list集合,而任何一个锁都有一个等待队列。生产者发现满了,它会先进等待队列,那么问题来了,一旦进到等待队列,那要等到什么时候呢?答案是等到别人通知你不需要再等的时候,那就是命令—notify(),等待和通知都是锁的行为,任何一把锁都是有一个等待队列的,而等待队列里放的都是些等待线程。一旦等待队列中出现通知,它就会把等待队列中的某一个线程唤醒。使它可以再次去抢占CPU运行,类似于休眠。在本程序中是生产者添加一个元素,它通知消费者可以删除元素了,反之,当满了的时候,消费者取出一个元素,通知生产者可以加入元素了。

程序改造–生产和消费动作都采用同步方法

  1. wait()—->Object定义的
  2. 锁都是有等待机制的,而任何对象第可以作为锁,所以任何对象都可以定义wait方法,此时,锁对象(Mylist)就进入了等待队列里了等待了。类似于thread.sleep()<—暂时让线程休眠一段时间。
  3. 如果想让等待队列里的线程被唤醒重新执行,那就需要用notify重新通知。
  4. 如果该线程被执行,那么该线程将会从wait()方法处的下一行代码开始继续执行。
  5. wait()和sleep()的相同点:二者都会让线停止,放弃CPU抢占权;不同点wait()等待的时候会释放锁的锁旗标,但是sleep()不会释放锁,且sleep()与锁对象的监控权无关。—>例:上厕所睡着了,wait()把门开开让别人进,而sleep还关着门不让别人进。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值