并发编程专题(三)

什么是多线程通讯?

多线程通讯就是多个线程同时操作一个资源,但是操作的动作不同

代码实现

package com.kernel;

class Res {
    private String name;
    private String sex;
    private Boolean flag;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public Boolean getFlag() {
        return flag;
    }

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

class InputThread extends Thread {
    private Res res;

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

    @Override
    public void run() {
        int count = 0;
        while (true) {
            synchronized (res) {
                if (res.getFlag()) {
                    try {
                        res.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                if (count == 0) {
                    res.setName("小红");
                    res.setSex("女");
                } else {
                    res.setName("小军");
                    res.setSex("男");
                }
                count = (count + 1) % 2;
                res.setFlag(true);
                res.notify();
            }
        }
    }
}

class OutputThread extends Thread {
    private Res res;

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

    @Override
    public void run() {
        while (true)
            synchronized (res) {
                if (!res.getFlag()) {
                    try {
                        res.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println(res.getName() + "," + res.getSex());
                res.setFlag(false);
                res.notify();
            }
    }
}

public class Test002 {
    public static void main(String[] args) {
        Res res = new Res();
        res.setFlag(false);
        InputThread inputThread = new InputThread(res);
        OutputThread outputThread = new OutputThread(res);
        inputThread.start();
        outputThread.start();
    }
}

为什么在不能使用 this.wait() ?

因为上面创建的两个线程分别是由两个类创建的,它们的对象不同,所以所对象不同。

为什么 wait、notify 属于 Object?

那是因为 wait、notify 需要使用到对象锁,众所周知,所有全局对象都可以作为对象锁,而 Object 是所有对象的父类,只要在 Object 实现了 wait、notify,所有类都可以使用到

wait、notify

因为 wait、notify 使用的是对象锁,所以它们必须放在 synchronize 中使用

wait 阻塞当前执行的线程

notify 唤醒锁池中的线程,使之运行

wait 与 join 的区别

wait 必须放置在 synchronize 中

join 不需要唤醒

wait 与 sleep 的区别

sleep 不需要放在 synchronize 中

sleep 不会释放锁

Lock 锁

lock 写法

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

Lock 与 Synchronsize 的区别

Lock 可以非阻塞获得锁,当前线程尝试获取锁,如果锁未被其他线程获取,则成功获得并持有锁

Lock 接口能被中断获取锁,获取到锁的线程能够响应中断,当获取到的锁的线程被中断时,中断异常将会被抛出,同时锁会被释放

Lock 接口在指定的截止时间之前获取锁,如果截止时间到了依旧无法获取锁,则返回

Condition 用法

Condition 相当于 wait 和 notify 的功能

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

class Res  {
    private String name;
    private String sex;
    private Boolean flag;
    Lock lock = new ReentrantLock();

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public Boolean getFlag() {
        return flag;
    }

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

class InputThread extends Thread {
    private Res res;
    Condition condition;

    public InputThread (Res  res, Condition condition) {
        this.res = res;
        this.condition = condition;
    }

    @Override
    public void run() {
        int count = 0;
        while (true) {
            try {
                res.lock.lock();
                if (res.getFlag()) {
                    try {
                        res.wait();
                        condition.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                if (count == 0) {
                    res.setName("小红");
                    res.setSex("女");
                } else {
                    res.setName("小军");
                    res.setSex("男");
                }
                count = (count + 1) % 2;
                res.setFlag(true);
                condition.signal();
            } catch (Exception e) {

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

class OutputThread  extends Thread {
    private Res res;
    Condition condition;

    public OutputThread (Res res, Condition condition) {
        this.res = res;
        this.condition = condition;
    }

    @Override
    public void run() {
        try {
            res.lock.lock();
            while (true) {
                if (!res.getFlag()) {
                    try {
                        condition.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println(res.getName() + "," + res.getSex());
                res.setFlag(false);
                condition.signal();
            }
        } catch (Exception e) {

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

    }
}

public class Test003 {
    public static void main(String[] args) {
        Res  res = new Res ();
        Condition condition = res.lock.newCondition();
        res.setFlag(false);
        InputThread inputThread = new InputThread(res, condition);
        OutputThread outputThread = new OutputThread(res, condition);
        inputThread.start();
        outputThread.start();
    }

}

原文地址:https://blog.51cto.com/13559120/2378487

时间: 2024-08-30 13:47:58

并发编程专题(三)的相关文章

并发编程专题(三)-线程的状态

1.线程状态 Java中,线程的状态使用一个枚举类型来描述的.这个枚举一共有6个值: NEW(新建).RUNNABLE(运行).BLOCKED(锁池).TIMED_WAITING(定时等待).WAITING(等待).TERMINATED(终止.结束).但是大多数人的理解和上面的这六种还是有些差别,通常会加上阻塞状态,可运行状态,挂起状态.在API中 java.lang.Thread.State 这个枚举中给出了六种线程状态,这是Thread类描述线程状态的枚举类的源代码: public enum

【Java并发编程】6、volatile关键字解析&内存模型&并发编程中三概念

转自:http://www.cnblogs.com/dolphin0520/p/3920373.html volatile这个关键字可能很多朋友都听说过,或许也都用过.在Java 5之前,它是一个备受争议的关键字,因为在程序中使用它往往会导致出人意料的结果.在Java 5之后,volatile关键字才得以重获生机. volatile关键字虽然从字面上理解起来比较简单,但是要用好不是一件容易的事情.由于volatile关键字是与Java的内存模型有关的,因此在讲述volatile关键之前,我们先来

并发编程(三):从AQS到CountDownLatch与ReentrantLock

一.目录 1.AQS简要分析 2.谈CountDownLatch 3.谈ReentrantLock 4.谈消费者与生产者模式(notfiyAll/wait.signAll/await.condition) 二.AQS简要分析 问题:AQS是什么?有什么用? AQS是什么? 字面上看,它被称为抽象队列式的同步器(AbstractQueuedSynchronizer).简单说,它就是一个同步队列容器. AQS有什么用? 为什么会产生ArrayList.LinkedList.HashMap这些容器?它

Java并发编程(三)volatile域

相关文章 Java并发编程(一)线程定义.状态和属性 Java并发编程(二)同步 Android多线程(一)线程池 Android多线程(二)AsyncTask源代码分析 前言 有时仅仅为了读写一个或者两个实例域就使用同步的话,显得开销过大,volatile关键字为实例域的同步訪问提供了免锁的机制.假设声明一个域为volatile,那么编译器和虚拟机就知道该域是可能被还有一个线程并发更新的. 再讲到volatile关键字之前我们须要了解一下内存模型的相关概念以及并发编程中的三个特性:原子性,可见

高并发编程专题说明

大家好,并发编程是一个提升程序员level的关键专题,本专题会从理论结合实践逐步深入,尽量用通俗的语言和跑的通的程序来给大家讲解,重点每个地方都会形成一个闭环,让大家真正掌握高并发编程的核心要点,让我们一起来学习,感受技术的乐趣. 对该专题感兴趣的,欢迎点赞!!! 最后给大家一个经验之谈,要提升自己的技术逼格,一句话,"不断走出自己的舒适区" 技术说明:本专题会以java作为编程语言,要求大家具备javase的基础知识,如果不具备就需要先掌握这部分知识再来看这个专题了. 原文地址:ht

Java并发编程专题

为了防止无良网站的爬虫抓取文章,特此标识,转载请注明文章出处.LaplaceDemon/ShiJiaqi. http://www.cnblogs.com/shijiaqi1066/p/4852149.html 明确并发编程中的一些基本概念 Java 并发(1)多线程基础 Java并发(2)线程安全与线程间通信 Java并发(3)同步容器与并发容器 Java并发(4) Executor框架 —— 线程池初步 Java并发(5)Executor框架 —— 线程池进阶 Java并发(6)带返回结果的任

Java并发编程(三)概念介绍

在构建稳健的并发程序时,必须正确使用线程和锁.但是这终归只是一些机制.要编写线程安全的代码,其核心在于要对状态访问操作进行管理,特别是对共享的(Shared)和可变的(Mutable)状态的访问. 对象的状态是指存储在状态变量(例如实例或静态域)中的数据. 对象的状态可能包括其他依赖对象的域.比如某个HashMap的状态不仅是HashMap对象本身,还存储在许多Map.Entry对象中. "共享"意味着变量可以由多个线程同时访问,而"可变"则意味着变量的值在其生命周

并发编程专题(一)-并发与多线程

1.并发 1.1 并发与并行 首先介绍一下并发与并行,两者虽然只有一字之差,但实际上却有着本质的区别,其概念如下: 并行性(parallel):指在同一时刻,有多条指令在多个处理器上同时执行: 并发性(concurrency):指在同一时刻只能有一条指令执行,但多个进程指令被快速轮换执行,使得在宏观上具有多个进程同时执行的效果. 在操作系统中,安装了多个程序,并发指的是在一段时间内宏观上有多个程序同时运行,这在单 CPU 系统中,每一时刻只能有一道程序执行,即微观上这些程序是分时的交替运行,只不

Java 并发编程(三)设计线程安全的类-实例封闭

到目前为止,我们已经介绍了关于线程安全与同步的一些基础知识.然而,我们并不希望对每一次内存访问都进行分析以确保是线程安全的,而是希望将一些现有的线程安全组件组合为更大规模的组合为更大规模的组件或程序.之后,我们会讲一些设计线程安全类的一些基本概念,介绍一些组合模式. 一.设计线程安全的类 在设计线程安全类的过程中,需要包含以下三个基本要素: 1.找出构成对象状态的所有变量 2.找出约束状态变量的不变性条件 3.建立对象状态的并发访问管理策略 要分析对象的状态,首先从对象的域开始.如果对象中所有的