class Res{
public String username;
public String sex;
}
class Out extends Thread{
Res res; public Out(Res res){
this.res=res;
}
@Override
public void run() {
//写操作
int count=0;
while (true){
// synchronized (res.getClass()){
if(count==0){//偶数
res.username="小明";
res.sex="男";
} else {//奇数
res.username="小红";
res.sex="女";
}
count=(count+1)%2;
// }
} }
}
class Input extends Thread{
Res res;
public Input(Res res){
this.res=res;
} @Override
public void run() {
while (true){
// synchronized (res.getClass()){
System.out.println(res.username+","+res.sex);
// }
}
}
}
public class OutInputThread {
public static void main(String[] args) {
Res res = new Res();
Out out = new Out(res);
Input input = new Input(res);
out.start();
input.start();
}
}

小红,女
小红,女
小红,女
小红,女
小红,女
小红,女
小红,女
小红,女
小红,女


出现以上结果??消费者一直消费或者生产者一直生产

解决方法:生产者生产完成后消费者方可消费,否者不可消费,消费者未消费或者未消费完生产者不可生产,一次生产一次消费。其实也就是保证对res共享资源的操作同一时刻仅有同一个线程进行操作,

wait、notify、notifyAll方法

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

这三个方法最终调用的都是jvm级的native方法。随着jvm运行平台的不同可能有些许差异。

如果对象调用了wait方法就会使持有该对象的线程把该对象的控制权交出去,然后处于等待状态。当前线程从运行变为阻塞,释放所的资源

如果对象调用了notify方法就会通知某个正在等待这个对象的控制权的线程可以继续运行。让持有该锁的线程从阻塞态变为就绪。

如果对象调用了notifyAll方法就会通知所有等待这个对象控制权的线程继续运行。

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

通过以下方式即可完成需求。

生产者获取res.getClass锁后,如果flag为true生产者通过调用res.getClass.wait进行等待,此时其他线程可获取该锁,如果flag为false,进行生产,然后设置flag为true保证资源消费后方可再生产,接着通过notify通知其他唤醒其他线程。

class Res{
public String username;
public String sex;
//true 生产者等待,消费者可消费 false生产者可以生产,消费者不可消费
public boolean flag=false;
}
class Out extends Thread{
Res res; public Out(Res res){
this.res=res;
}
@Override
public void run() {
//写操作
int count=0;
while (true){
synchronized (res.getClass()){
if(res.flag){
try {
res.getClass().wait();//让当前线程从运行变为阻塞,并且释放所的资源
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if(count==0){//偶数
res.username="小明";
res.sex="男";
} else {//奇数
res.username="小红";
res.sex="女";
}
count=(count+1)%2;
res.flag=true;
res.getClass().notify();
}
} }
}
class Input extends Thread{
Res res;
public Input(Res res){
this.res=res;
} @Override
public void run() {
while (true){
synchronized (res.getClass()){
if(!res.flag){
try {
res.getClass().wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(res.username+","+res.sex);
res.flag=false;
res.getClass().notify();
}
}
}
}
public class OutInputThread {
public static void main(String[] args) {
Res res = new Res();
Out out = new Out(res);
Input input = new Input(res);
out.start();
input.start();
}
} 输出如下:
小明,男
小红,女
小明,男
小红,女
小明,男
小红,女
小明,男
小红,女

如果去掉notify会怎样?去掉一个?去掉两个?

去掉一个生产者可以打印多个(但是也不多),去掉消费者仅可打印一个,去掉两个可能不打印,也可能打印1个,所以wait、notify必须成对使用

wait(用于同步中)与sleep区别?

都是做休眠,wait需要notify

对于sleep方法,我们首先要知道该方法是属于Thread类中的。而wait方法,则是属于Object类中的。

sleep方法导致了程序暂停执行指定的时间,让出cpu该其他线程,但是他的监控状态依然保持者,当指定的时间到了又会自动恢复运行状态。

在调用sleep方法的过程中,线程不会释放对象锁。

而当调用wait方法的时候,线程会放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象调用notify方法后本线程才进入对象锁定池准备获取对象锁进入运行状态。

最新文章

  1. 从业十余年谈谈对dotnet看法与坚持
  2. Linux下MySQL/MariaDB Galera集群搭建过程
  3. Electronic oscillator
  4. SQL时间相关
  5. [转]Linux后台进程管理利器:supervisor
  6. [py]shell着色
  7. %SELECTALL
  8. word2010中怎样快速修改同级标题格式
  9. 齐B小短裙
  10. 井字棋(Tic-Tac-Toe)
  11. 3. SQL Server数据库状态监控 - 可用空间
  12. 【最短路】 ZOJ 1544 Currency Exchange 推断负圈
  13. [Luogu 1402] 酒店之王
  14. mongoDB概述
  15. [RHEL 6]GPT分区--parted
  16. 解决Linux终端乱码的两则例子
  17. WPF 实现主从的datagrid以及操作rowdetailtemplate 的方法
  18. bootstarp3
  19. Oracle 导出错误 EXP-00000~EXP-00107
  20. Beta 冲刺 六

热门文章

  1. 使用BP拦截POST型请求包
  2. tools.sublime.ConvertToUTF8
  3. python重要函数eval
  4. Django(五)1 - 4章实战:从数据库读取图书列表并渲染出来、通过url传参urls.py path,re_path通过url传参设置、模板语法
  5. 前端学习(22)~css问题讲解
  6. Gym 101158D(暴力)
  7. uni-app解决小程序圆角样式不生效
  8. 51nod 1439:互质对 容斥原理
  9. 配置vSphere Web Client超时值
  10. jsp与spring mvc后台controller间参数传递处理之总结