美文网首页
多线程2

多线程2

作者: 半年很快 | 来源:发表于2018-06-22 20:34 被阅读0次

    线程之间的通信:---打印机

    分析:两个线程:输入线程和输出线程
    两个任务:输入任务和输出任务
    一个数据:要被两个线程共享

    代码书写步骤:
    1.创建数据类
    2.创建任务类
    3.创建线程对象并工作

    其中在数据类中实现的时候,需要判断线程是否安全,此时需要用到synchronized
    给输入任务与输出任务同时加锁,保证两个任务是同步的
    需要给两个任务加同一把锁:
    这把锁可以使Object.class,但由于Object的使用范围太广,可能造成不必要的错误,所以不建议使用,还可以使用数据类的对象,因为此对象本身就是被两个任务共享的对象,所以充当锁最适合
    synchronized在修饰语句的时候,锁可以自己写,在修饰非静态方法时,锁默认的是this,在修饰静态方法时,锁默认的是当前类的字节码文件

    使用等待唤醒机制的前提:1.多线程 2.已经用synchronized同步了
    使用方法:等待唤醒机制,具体方法notify()/notifyAll(),wait()
    wait():让当前的线程变成了等待的状态,放入了一个池子(线程池),失去了抢cpu的能力,等待唤醒(锁想相当于给当前的线程做了一个标记)
    notify():将当前的线程从等待状态唤醒,相当于从池子中取出线程。(唤醒的是同一把锁的任意一个线程)
    注意点:
    wait()是Object类里面的方法,所以可以被任何子类调用
    wait、notify等方法必须由锁对象调用
    在写wait()方法时,会报错,报错后,鼠标放在错误上面添加try...catch...方法就可以了

    前面解决的都是单生产单消费者的问题:
    现在解决多生产者多消费者问题:
    分析:
    生产者有生产任务
    消费者有消费任务

    需要创建的对象:
    多个生产线程、多个消费线程
    两个任务:生产任务、消费任务
    一个数据:产品

    错误分析:
    当有两个消费线程的时候,有可能出现生产一次消费一次,或者生产多次消费一次的情况
    原因:当线程被重新唤醒之后,没有判断标记,而是执行执行了下面的代码

    解决的办法:将if换成while(换完之后再进程序就需要重新判断)

    继续:继续运行程序会出现死锁的情况(4个线程同时处于等待状态)
    原因:唤醒的是本方的线程,导致所有的线程都处于等待的状态

    解决:将notify换成notifyAll:保证对方线程的唤醒
    死锁:
    1.所有的线程都处于等待状态
    2.锁之间进行了嵌套作用

    jdk1.5之后新增了lock和signal来替代了synchronized
    lock()和unlock()是Lock类里面的方法
    lock()相当于synchronized的左括号
    lock()相当于synchronized的右括号
    这两个方法必须实现,所以要用到try{}finally{}方法
    而await和signal()是Condition类里面的方法
    其中Lock类里面有个newCondition方法可以直接创建Condition的对象

    实例:
    多生产者多消费者
    分析:
    线程:多个生产者和多个消费者
    任务:生产和消费
    数据:产品
    现列举数据类中生产者的活的代码
    class Product{
    String name;
    int price;
    int count;
    boolean flag = false;
    private final Lock lock=new ReentrantLock()://Lock是个借口
    Condition condition1 = lock.newCondition();
    Condition cindition2= lock.newCondition();
    public void produce(String name,int price){
    try{
    lock.lock();
    while(flag==true){
    try{
    condition1.await
    }catch(InterruptedException e){
    e.printStackTrace();
    }
    this.name = name;
    this.price = price;
    System.out.println(Thread.currentThread().getName()+" 生产了:"+name+" 产品的数量:"+count+" 价格:"+price);

            count++;
                      flag = !flag;
                      condition2.signal();
    

    }
    }finally{
    lock.unlock();
    }
    }
    }

    线程的停止:控制任务区的结束,只要任务没有结束,线程就不会停止
    1.通过一个标识符停止线程
    2.调用stop方法--已经过时,有固有的安全性,不建议使用
    3.调用interrupt方法让长期处理wait状态的线程停止

    守护线程:相当于后台线程(操作不到的线程,看不见),依赖于前台线程(正在运行,可以看到的,例:主线程),正常情况下,当前台线程结束的时候,不管守护线程是不是还在工作,都会立刻结束
    典型的守护线程:垃圾回收线程

    当一个线程调用了setDaemon()方法,并将参数设置成true,这个线程就变成了守护线程
    注意:这个方法一定要在start()方法之前调用
    形式:Thread thread = new Thread(new Test1())
    thread.setDaemon(true);
    thread.start();
    此时,thread线程就是守护线程,随着前台线程的结束而结束

    join()方法:
    原理:线程一旦调用join方法,他的优先级就会高于主线程,主线程会等当前的线程执行完之后再去执行
    注意:这个线程的优先级只是比主线程的高,对其他线程没有影响;且join加到start()后面,线程开启后,再调用此方法
    作用:当我们希望当前线程对应的任务在主线程之前完成
    Thread thread1 = new Thread(new Test());
    thread1.start();
    thread1.join();
    此时thread1的优先级就比主线程的高,会优先于主线程执行

    相关文章

      网友评论

          本文标题:多线程2

          本文链接:https://www.haomeiwen.com/subject/oqdcyftx.html