线程--简单多线程通信实例

1、多线程通信

两个线程同时操作一个存储空间,一个存数据,一读数据。并且按照一定的顺序轮流执行。Object提供wait(),notify(),notify All(),方法用于解决线程间通信问题。

1.1、代码
package com.example;


public class MyThreadCommit {
    public static void main (String [] args){

    Storage st = new Storage();//创建数据存储类对象
    Input input = new Input(st);//创建Input 对象传入Storage对象
        Output output = new Output(st);//创建传入Storage对象
        new Thread(input).start();
        new Thread(output).start();
    }
}

class Input implements  Runnable{ //输入线程
    private  Storage st;
    private int num; //定义一个变量
    Input(Storage st){  //通过构造方法来接受一个Storage对象
        this.st=st;
    }
    public  void  run(){
        while (true){
            st.put(num++); //将num存入数组,每次存入后 +1
        }
    }
}

class Output implements  Runnable{//输出线程类
    private Storage st;
    Output(Storage st){
        this.st=st; //构造方法接受一个Storage 对象
    }
    public void run(){
        while(true){
            st.get(); //循环取出元素
        }
    }

}

class Storage {
    private int [] cells = new int[10]; //数据存储数组
    private int inPos,outPos;//inPos 存入时的数组下标,outPos取出时的数组下标
    private int count; //存入或取出时数据的数量
    public synchronized void put(int num){
            try {
                while (count == cells.length){
                this.wait(); 
            }
            cells[inPos]=num;//向数组中放入数据
            System.out.println("在cells["+inPos+"]中放入数据---"+cells[inPos]);
            inPos++; //存完元素让位置加1
            if (inPos == cells.length){
                inPos = 0; //当cells[9]放完数据后再从cells[0]开始
            }
            count ++; //每方一个数据count 加1
            this.notify();
            } catch (InterruptedException e) {
                e.printStackTrace();

        }
    }

    public synchronized  void get(){
            try {
                while (count == 0) { //如果count为0,此线程等待
                    this.wait();
                }
                int data = cells[outPos];//从数组中取出数据
                System.out.println("在cells["+outPos+"]中取出数据---"+data);
                cells[outPos]=0;//当取出数据时,当前数据值为0
                outPos++;//取万后位置+1
                if(outPos == cells.length){
                    outPos=0;//当从cells[9]中取完数据后再从cells[0]开始
                }
                count--;//每取一个元素count -1
                this.notify();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }


1.2、运行结果

在cells[2]中放入数据---3759862
在cells[3]中放入数据---3759863
在cells[4]中放入数据---3759864
在cells[5]中放入数据---3759865
在cells[6]中放入数据---3759866
在cells[7]中放入数据---3759867
在cells[8]中放入数据---3759868
在cells[9]中放入数据---3759869
在cells[0]中放入数据---3759870
在cells[1]中取出数据---3759861
在cells[2]中取出数据---3759862
在cells[3]中取出数据---3759863
在cells[4]中取出数据---3759864
在cells[5]中取出数据---3759865
在cells[6]中取出数据---3759866
在cells[7]中取出数据---3759867
在cells[8]中取出数据---3759868
在cells[9]中取出数据---3759869
在cells[0]中取出数据---3759870
在cells[1]中放入数据---3759871
在cells[2]中放入数据---3759872
在cells[3]中放入数据---3759873
在cells[4]中放入数据---3759874

首先使用synchorized关键字将put()方法和get()方法修饰为同步方法,之后每操作一次数据,便调用一次notify()方法唤醒 对应同步锁上等待的线程。
当存入数据时,如果count的值和cells数组的长度相等,说明数组已经填满,此时调用同步锁的wait()方法使存入数据的线程进入等待状态。
当取出数据时,如果count的值为0,说明数组已经被取空,此时就需要调用同步锁的wait()方法,使取出数据的线程进入等待状态。

参考文档:
Java基础入门 传智博客高教产品研发部 

本人郑重声明,本博客所著文章、图片版权归权利人持有,本博只做学习交流分享所用,不做任何商业用途。访问者可將本博提供的內容或服务用于个人学习、研究或欣赏,不得用于商业使用。同時,访问者应遵守著作权法及其他相关法律的规定,不得侵犯相关权利人的合法权利;如果用于商业用途,须征得相关权利人的书面授权。若以上文章、图片的原作者不愿意在此展示內容,请及时通知在下,將及时予以刪除。

你可能感兴趣的:(java,基础)