多线程之间实现通讯

1、什么是多线程之间通讯?

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

2、多线程之间通讯需求

需求:第一个线程写入(input)用户,另一个线程取读取(out)用户,实现写一个,读一个的操作。

img

代码演示如下:

共享资源实体类

class Res {

    public String userSex;

    public String userName;

}

输入线程资源

class InpThread extends Thread {

	private Res res;

 

	public InpThrad(Res res) {

            this.res = res;

	}

 

	@Override

	public void run() {

            int count = 0;

            while (true) {

		if (count == 0) {

		    res.userName = "小明";

		    res.userSex = "男";

		} else {

		    res.userName = "小红";

		    res.userSex = "女";

		}

		count = (count + 1) % 2;

	    }

	}

}

输出线程

class OutThread extends Thread {

	private Res res;

 

	public OutThread(Res res) {

	    this.res = res;

	}

 

	@Override

	public void run() {

            while (true) {

                System.out.println(res.userName + "--" + res.userSex);

	      }

	}

}

运行代码

public static void main(String[] args) {

        Res res = new Res();

	InpThrad inpThrad = new InpThrad(res);

	OutThread outThread = new OutThread(res);

	intThrad.start();

	outThread.start();

}

运行结果

img

注意:此时数据会发生错乱,造成线程安全问题

那么解决好线程安全问题,运行结果又会是怎样的呢?

在输入线程InpThread 类中加上synchronized

class InpThread extends Thread {

	private Res res;

 

	public InpThrad(Res res) {

		this.res = res;

	}

 

	@Override

	public void run() {

            int count = 0;

	    while (true) {

		synchronized (res) {

		if (count == 0) {

		    res.userName = "小明";

		    res.userSex = "男";

		} else {

		    res.userName = "小红";

		    res.userSex = "女";

		}

		count = (count + 1) % 2;

	        }

	    }

        }

}

在输出线程OutThread 类中加上synchronized

class OutThread extends Thread {

	private Res res;

 

	public OutThread(Res res) {

		this.res = res;

	}

 

	@Override

	public void run() {

            while (true) {

	        synchronized (res) {

		    System.out.println(res.userName + "--" + res.userSex);

		}

	    }

	}

}

那么此时的运行结果是怎样的呢?

img

注意:InpThread 和 OutThread两个线程同时并行进行,在OutThread线程获取到CPU时会进行多次打印,并不会实现依次打印的效果

那么怎样才能实现依次打印这种效果呢?

3、wait()、notify()、notifyAll()方法

wait()、notify()、notifyAll()是三个定义在Object类里的方法,可以用来控制线程的状态。

如果对象调用了wait方法就会使持有该对象的线程把该对象的控制权交出去,然后处于等待状态。
如果对象调用了notify方法就会通知某个正在等待这个对象的控制权的线程可以继续运行。
如果对象调用了notifyAll方法就会通知所有等待这个对象控制权的线程继续运行。
使用这三个方法就可以实现线程之间同步,达到了写一个读一个的效果。

代码演示

共享资源实体类

class Res {

	public String userSex;

	public String userName;

	//线程通讯标识

	public boolean flag = false;

}

输入线程

class InpThrad extends Thread {

	private Res res;

 

	public InpThrad(Res res) {

		this.res = res;

	}

 

	@Override

	public void run() {

            int count = 0;

            while (true) {

	        synchronized (res) {

		if (res.flag) {

		    try {

			// 当前线程变为等待,但是可以释放锁

		        res.wait();

		    } catch (Exception e) {

                        // TODO: handle exception

		    }

		  }

		if (count == 0) {

		    res.userName = "小明";

		    res.userSex = "男";

		} else {

		    res.userName = "小红";

		    res.userSex = "女";

		}

		count = (count + 1) % 2;

		res.flag = true;

		// 唤醒其他等待线程

		res.notify();

		}

	    }

	}

}

输出线程

class OutThread extends Thread {

	private Res res;

 

	public OutThread(Res res) {

	    this.res = res;

	}

 

	@Override

	public void run() {

	    while (true) {

	        synchronized (res) {

	        if (!res.flag) {

		    try {

                        res.wait();

		    } catch (Exception e) {

		        // TODO: handle exception

                    }

		}

 

		System.out.println(res.userName + "--" + res.userSex);

		res.flag = false;

		res.notify();

		}

	    }

        }

}

运行结果

img

此时线程之间同步,达到了写一个读一个的效果。

————————————————
版权声明:本文为CSDN博主「有头发的代码匠」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/Mr_wxc/article/details/105660052

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值