/*
1.增加一个知识点
一个类怎么在所有的类中,让其它类来共同修改它的数据呢?
可以用单例设计模式
可以用静态
可以在其它类中做一个构造函数,接受同一个对象,这样就可以实现对象

2.状态选择
可以用数字0 1 判断
可以用bool
注意变量的范围即可

3.加了同步后,还是有安全怎么办?
想前提!  1.  两个及以上线程(同步的)  2.操作公用资源  3.要用同一锁
*/

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

*/

/*
1.为什么会出现安全问题?
就是不满足前提呗

2.我们还没有了解到线程的本质
1.线程的执行时互相争抢执行权的
2.如果没有同步代码块的话,就会对数据进行胡乱修改,有可能修改到一半,另一个线程进来,有可能修改好几次,等等,甚至还会无视条件
3.即便有了同步代码块,也不能保证代码是按次序相互执行,因为,第一个线程执行完之后,还会参与下一次的争抢当中来,拥有相同的争抢概率
所以就出现同步中的不同步状况,这时候就要用到唤醒
4.其实程序就是一个逻辑判断问题,就是看有没有数据
*/

/*五种状态之一的等待
1.是Thread从上帝那里继承来的
2.而且这个函数是抛了异常的,根据异常的格式,要try和catch
3.唤醒也是继承上帝的
4.使用的时候,直接用对象点出来就可以
5.这样很容易区分,也造成为什么要把这两个函数写在上帝里面的原因,锁是任意类型的,什么对象都可以

*/
class Res                                   /*定义一个类,里面封装好数据成员,用来去调用*/
{
    String name;
    String sex;
    boolean flag = false;      /*用来判断是否已经存入数据,封装好用来调用*/
}

class Input implements Runnable
{
    private Res r ;
    Input(Res r)
    {
        this.r = r;
    }
    public void run()
    {
        int x = 0;
        while(true)
        {
            synchronized(r)             /*只能让一个线程进来,而且输入的先进来,输出的就不给进了,这样就满足了前提,有两个线程,同一锁,公共资源*/
            {

if(r.flag)               /*真,冻结*/
                    try{r.wait();}catch(Exception e){}     /*线程池,等待线程都在线程池当中,唤醒的是什么,唤醒的都是线程池当中的线程*/
                if(x==0)
                {
                    r.name="mike";                    /*赋值*/
                    r.sex="man";
                }
                else
                {
                    r.name="丽丽";
                    r.sex = "女女女女女";
                }
                x = (x+1)%2;               /*转换性别*/
                r.flag = true;    
                r.notify();       /*有就唤醒,没有就不唤醒,按顺序来自然就不需要这个,唤醒的是另一个线程*/
            }
        }
    }
}

class Output implements Runnable
{
    private Res r ;            /*对象数据成员*/
    
    Output(Res r)
    {
        this.r = r;                  /*传递对象进来*/
    }
    public void run()
    {
        while(true)
        {
            synchronized(r)             /*放的是对象*/
            {
                if(!r.flag)
                    try{r.wait();}catch(Exception e){}
                System.out.println(r.name+"...."+r.sex);            /*删除*/
                r.flag = false;    
                r.notify();                                 /*唤醒输入线程*/
            }
        }
    }
}

class  InputOutputDemo
{
    public static void main(String[] args)
    {
        Res r = new Res();                     /*封装好的类,将会当作参数,传递给其它类*/

Input in = new Input(r);               /*实现多线程类的对象*/
        Output out = new Output(r);

Thread t1 = new Thread(in);          /*开启线程,把实现线程的对象放进来*/
        Thread t2 = new Thread(out);

t1.start();                  /*开启线程,调用run函数*/
        t2.start();
    }
}

//notifyAll();

/*
wait:
notify();
notifyAll();

都使用在同步中,因为要对持有监视器(锁)的线程操作。
所以要使用在同步中,因为只有同步才具有锁。

为什么这些操作线程的方法要定义Object类中呢?
因为这些方法在操作同步中线程时,都必须要标识它们所操作线程只有的锁,
只有同一个锁上的被等待线程,可以被同一个锁上notify唤醒。
不可以对不同锁中的线程进行唤醒。

也就是说,等待和唤醒必须是同一个锁。

而锁可以是任意对象,所以可以被任意对象调用的方法定义Object类中。

*/

代码优化:
/*
线程间通讯:
其实就是多个线程在操作同一个资源,
但是操作的动作不同。

*/
class Res
{
    private String name;
    private String sex;
    private boolean flag = false;

public synchronized void set(String name,String sex)
    {
        if(flag)
            try{this.wait();}catch(Exception e){}             /*记住,加同步的是共同操作的数据,不是定义数据,是会变动的数据*/
        this.name = name;
        
        this.sex = sex;
        flag = true;
        this.notify();                                       /*this代表同步函数的锁,也代表当前对象*/
    }
    public synchronized void out()
    {
        if(!flag)
            try{this.wait();}catch(Exception e){}
        System.out.println(name+"........"+sex);
        flag = false;
        this.notify();
    }
}

class Input implements Runnable
{
    private Res r ;                 /*用来接收同一个对象*/
    Input(Res r)
    {
        this.r = r;
    }
    public void run()
    {
        int x = 0;
        while(true)
        {
            if(x==0)                
                r.set("mike","man");    /*这个函数已经是同步函数了*/            
            else    
                r.set("丽丽","女女女女女");                
            x = (x+1)%2;
        }
    }
}

class Output implements Runnable
{
    private Res r ;
    
    Output(Res r)
    {
        this.r = r;
    }
    public void run()
    {
        while(true)
        {
            r.out();       /*不断输出*/
        }
    }
}

class  InputOutputDemo2
{
    public static void main(String[] args)
    {
        Res r = new Res();

new Thread(new Input(r)).start();            /*全部使用无名对象,优化代码*/
        new Thread(new Output(r)).start();
        /*
        Input in = new Input(r);
        Output out = new Output(r);

Thread t1 = new Thread(in);
        Thread t2 = new Thread(out);

t1.start();
        t2.start();
        */
    }
}

Java多线程间通信-解决安全问题、等待唤醒机制的更多相关文章

  1. Java 多线程间通信

    JDK 1.5 以后, 将同步和锁封装成了对象, 并将操作锁的隐式方法定义到了该对象中, 将隐式动作变成了显示动作. Lock 接口 Lock 接口, 位于 java.util.concurrent. ...

  2. Java 线程之间的通讯,等待唤醒机制

    public class ThreadNotifySample { public static void main(String[] args) { // Res res = new Res(); / ...

  3. java 多线程间通信(二)

    传统的线程通信 Object提供了三个方法wait(), notify(), notifyAll()在线程之间进行通信,以此来解决线程间执行顺序等问题. wait():释放当前线程的同步监视控制器,并 ...

  4. java 多线程间通信(一)

    synchronized同步 package com.test7; public class Run { public class MyObject { private int a; public M ...

  5. java 中多线程之间的通讯之等待唤醒机制

    wait notify () nitifyAll () 都使用在同步中,因为要对持有监视器(锁)的线程操作 所以要使用在同步中,因为只有同步才具有锁 为什么这些操作线程的方法要定义object类中呢 ...

  6. 阶段1 语言基础+高级_1-3-Java语言高级_05-异常与多线程_第4节 等待唤醒机制_1_线程状态概述

    Thread中有个嵌套类 它描述了线程的状态 线程状态的图 Object类中的Wait方法和notify方法

  7. java基础知识回顾之java Thread类学习(八)--java多线程通信等待唤醒机制经典应用(生产者消费者)

     *java多线程--等待唤醒机制:经典的体现"生产者和消费者模型 *对于此模型,应该明确以下几点: *1.生产者仅仅在仓库未满的时候生产,仓库满了则停止生产. *2.消费者仅仅在有产品的时 ...

  8. java基础知识回顾之java Thread类学习(七)--java多线程通信等待唤醒机制(wait和notify,notifyAll)

    1.wait和notify,notifyAll: wait和notify,notifyAll是Object类方法,因为等待和唤醒必须是同一个锁,不可以对不同锁中的线程进行唤醒,而锁可以是任意对象,所以 ...

  9. JAVA之旅(十四)——静态同步函数的锁是class对象,多线程的单例设计模式,死锁,线程中的通讯以及通讯所带来的安全隐患,等待唤醒机制

    JAVA之旅(十四)--静态同步函数的锁是class对象,多线程的单例设计模式,死锁,线程中的通讯以及通讯所带来的安全隐患,等待唤醒机制 JAVA之旅,一路有你,加油! 一.静态同步函数的锁是clas ...

随机推荐

  1. NGUI学习笔记(二):基础笔记

    精灵(Sprite).图集(Atlas)和贴图(Texture)的区别 图集:由多张小图拼合而成的一张大图,其好处是降低DrawCall的次数.减少载入内存的次数和方便管理同一类型的小图.一般图集都会 ...

  2. mybatis 打印sql log配置

    mybatis 打印sql log, 方便调试.如何配置呢? log4j.xml : <!-- 打印sql start --> <appender name="IBatis ...

  3. ServletContext1

    ---------------ConfigServlet.java----------- protected void doGet(HttpServletRequest request, HttpSe ...

  4. centos6下安装部署hadoop2.2

    环境准备1.操作系统:centos6.0 64位2.hadoop版本:hahadoop-2.2.0 安装和配置步骤具体如下:1.主机和ip分配如下     ip地址                  ...

  5. windows环境下搭建ffmpeg开发环境

           ffmpeg是一个开源.跨平台的程序库,能够使用在windows.linux等平台下,本文将简单解说windows环境下ffmpeg开发环境搭建过程,本人使用的操作系统为windows ...

  6. ios开发——实用技术OC-Swift篇&触摸与手势识别

    iOS开发学习之触摸事件和手势识别   iOS的输入事件 触摸事件 手势识别 手机摇晃 一.iOS的输入事件   触摸事件(滑动.点击) 运动事件(摇一摇.手机倾斜.行走),不需要人为参与的 远程控制 ...

  7. EntityFramework小知识

    Entity Framework 应用程序有以下优点: 1 应用程序可以通过更加以应用程序为中心的概念性模型(包括具有继承性.复杂成员和关系的类型)来工作. 2 应用程序不再对特定的数据引擎或存储架构 ...

  8. Fast portable non-blocking network programming with Libevent--转

    Learning Libevent Chapter 0: About this document Chapter 1: A tiny introduction to asynchronous IO. ...

  9. 手把手教你反编译别人的app

    虽然iOS系统相比于其他手机操作系统相对安全,但是这个安全并不是绝对的,我一直相信,道高一尺魔高一丈.此文想以实际例子出发,告诉大家,如何去反编译一个app,并且从某个角度来说,iOS没有传说中的“安 ...

  10. mfc模态对话框

    Mfc模态对话框: 创建模态对话框: [模态对话框:具有独占行为,必须由用户完成对当前对话框的响应,才能对本对话框所属的进程进行其他操作] 例如: 我们创建一个加法计算器.点击计算之后,弹出一个对话框 ...