美文网首页
多线程之间的通讯(第三天)

多线程之间的通讯(第三天)

作者: hzhang94 | 来源:发表于2018-09-27 15:20 被阅读0次

什么是线程之间的通信

多线程之间通讯,其实就是多个线程在操作同一个资源,但是操作的动作不同。

实现多线程直接的通讯

wait()、notify、notifyAll()方法

  1. wait()、notify()、notifyAll()是三个定义在Object类里的方法,可以用来控制线程的状态。
  2. 这三个方法最终调用的都是jvm级的native方法。随着jvm运行平台的不同可能有些许差异。
  3. 如果对象调用了wait方法就会使持有该对象的线程把该对象的控制权交出去,然后处于等待状态。
  4. 如果对象调用了notify方法就会通知某个正在等待这个对象的控制权的线程可以继续运行。
  5. 如果对象调用了notifyAll方法就会通知所有等待这个对象控制权的线程继续运行。

注意:一定要在线程同步中使用,并且是同一个锁的资源

wait()和notify()的使用示例

package top.nightliar.study.day04;

/**
 * 生产者,消费者(生产者生产一个,消费者消费一个,交替循环)
 * Created by Nightliar
 * 2018-09-13 15:35
 */
public class ThreadDemo01 {

    public static void main(String[] args) {
        Res res = new Res();
        new InPut(res).start();
        new OutPut(res).start();
    }

}

/**
 * 生成者,重新定义res对象的信息
 */
class InPut extends Thread{

    private boolean fl = false;

    private Res res;

    public InPut(Res res) {
        this.res = res;
    }

    @Override
    public void run() {
        while (true) {
            synchronized (res) {
                if (res.flag){
                    try {
                        res.wait();       // res为两个共享的锁资源
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                if (fl){
                    res.name = "张三";
                    res.sex = "男";
                    fl = false;
                }else {
                    res.name = "小红";
                    res.sex = "女";
                    fl = true;
                }
                res.flag = true;
                res.notify();
            }
        }
    }

}

/**
 * 消费者,输出res信息
 */
class OutPut extends Thread{

    private Res res;

    public OutPut(Res res) {
        this.res = res;
    }

    @Override
    public void run() {
        while (true) {
            synchronized (res) {
                if (!res.flag){
                    try {
                        res.wait();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
                System.out.println(res.name + "," + res.sex);
                res.flag = false;
                res.notify();
            }
        }
    }

}

class Res {
    public boolean flag;
    public String name;
    public String sex;
}

Lock的用法

Lock 接口与 synchronized 关键字的区别

  1. Lock 接口可以尝试非阻塞地获取锁 当前线程尝试获取锁。如果这一时刻锁没有被其他线程获取到,则成功获取并持有锁。
  2. Lock 接口能被中断地获取锁 与 synchronized 不同,获取到锁的线程能够响应中断,当获取到的锁的线程被中断时,中断异常将会被抛出,同时锁会被释放。
  3. Lock 接口在指定的截止时间之前获取锁,如果截止时间到了依旧无法获取锁,则返回。

Lock的写法

Lock lock  = new ReentrantLock();
lock.lock();
try{
    //可能会出现线程安全的操作
}finally{
    //一定在finally中释放锁
    //也不能把获取锁在try中进行,因为有可能在获取锁的时候抛出异常
    lock.ublock();
}

Condition用法

Condition的功能类似于在传统的线程技术中的,Object.wait()和Object.notify()的功能。

Condition condition = lock.newCondition();
res. condition.await();  类似wait
res. Condition. Signal() 类似notify

使用Condition代替wait和notify

package top.nightliar.study.day04;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 生产者,消费者(生产者生产一个,消费者消费一个,交替循环)
 * Created by Nightliar
 * 2018-09-13 15:35
 */
public class ThreadDemo02 {

    public static void main(String[] args) {
        Res2 res = new Res2();
        Condition condition = res.lock.newCondition();
        new InPut2(res, condition).start();
        new OutPut2(res, condition).start();
    }

}

/**
 * 生产者,重新定义res对象的信息
 */
class InPut2 extends Thread{

    private boolean fl = false;

    private Res2 res;

    private Condition condition;

    public InPut2(Res2 res, Condition condition) {
        this.res = res;
        this.condition = condition;
    }

    @Override
    public void run() {
        while (true) {
            try {
                res.lock.lock();
                if (res.flag){
                    condition.await();
                }
                if (fl){
                    res.name = "李四";
                    res.sex = "男";
                    fl = false;
                }else {
                    res.name = "小红";
                    res.sex = "女";
                    fl = true;
                }
                res.flag = true;
                condition.signal();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                res.lock.unlock();
            }

        }
    }

}

/**
 * 消费者,输出res信息
 */
class OutPut2 extends Thread{

    private Res2 res;

    private Condition condition;

    public OutPut2(Res2 res, Condition condition) {
        this.res = res;
        this.condition = condition;
    }

    @Override
    public void run() {
        while (true) {
            try {
                res.lock.lock();
                if (!res.flag){
                    condition.await();
                }
                System.out.println(res.name + "," + res.sex);
                res.flag = false;
                condition.signal();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                res.lock.unlock();
            }
        }
    }

}

class Res2 {
    public boolean flag;
    public String name;
    public String sex;
    public Lock lock = new ReentrantLock();
}

锁的类型

  • 可重入锁:在执行对象中所有同步方法不用再次获得锁。
  • 可中断锁:在等待获取锁过程中可中断。
  • 公平锁: 按等待获取锁的线程的等待时间进行获取,等待时间长的具有优先获取锁权利。
  • 读写锁:对资源读取和写入的时候拆分为两个部分处理,读的时候可以多线程一起读,写的时候必须同步地写。

笔试题

  1. lock锁与synchronized同步锁的区别?
    • Java的关键字,在jvm层面上,lock是一个接口。
    • lock锁手动上锁,手动释放,灵活性高,synchronized自动上锁和解锁。
    • synchronized线程执行发生异常,jvm会让线程释放锁,lock在finally中必须释放锁,不然容易造成线程死锁。

相关文章

  • 多线程(三)——多线程之间通讯

    什么是多线程之间通讯 多线程之间通讯,其实就是多个线程在操作同一个资源,但是操作的动作不同。 多线程之间通讯需求:...

  • 3.多线程之间通讯

    什么是多线程之间通讯? 多线程之间通讯,其实就是多个线程在操作同一个资源,但是操作的动作不同。 多线程之间通讯需求...

  • 多线程之间的通讯(第三天)

    什么是线程之间的通信 多线程之间通讯,其实就是多个线程在操作同一个资源,但是操作的动作不同。 实现多线程直接的通讯...

  • 线程之间如何进行通讯

    什么是多线程之间的通讯 多个线程对同一个资源(共享资源),每个线程对共享资源做的动作或者操作不同 多线程通讯的生产...

  • 7.2 多线程-NSThreed

    多线程-NSThreed.png NSThread案列 NSThread线程之间的通讯 NSThread线程的优先...

  • GCD的使用

    GCD的详解iOS多线程--彻底学会多线程之『GCD』 GCD线程之间的通讯 一般在主线程里面刷新UI 点击、滚动...

  • 21 多线程

    多和线程多听一个对象实现,实现不同的操作,过程可以称作为多线程之间实现通讯

  • 多线程如何实现同步-多线程之间通讯

    一. 什么是线程安全问题 多线程同时对同一个全局变量做写的操作,可能会受到其他 线程的干扰,就会发生线程安全性问题...

  • 10.3多线程详解

    Java高级-多线程 多线程创建 多线程通讯 线程池 1.多线程创建 thread/runnable图:继承Thr...

  • java Object.wait notify等待通知机制的理解

    在java多线程中可以使用object.wait/notify来进行线程之间的通讯 wait会使当前线程进入等待状...

网友评论

      本文标题:多线程之间的通讯(第三天)

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