线程间通讯:多个线程在处理同一资源,但是任务不同

练习一:双线程出现线程安全问题,需要使用同步,思考同步代码添加位置
需求:银行账户存钱,显示谁在账户存钱了,存了多少钱
分析:
操作同一银行账户
两个不同的操作,一个是存,一个是显示
这个两个操作可以同时执行

代码:

 class Bank
{
String name;//存钱人名
int amount; //无论是存还是取应该都是银行的动作
void put(String name,int amount)
{
this.name=name;
this.amount=amount;
} void take()
{
System.out.println(this.name+"---"+this.amount);
}
}
//定义对象实现Runnable,设置线程任务
class Input implements Runnable
{
private Bank b;
//使用构造函数保证存钱和显示同一资源
public Input(Bank b)
{
this.b=b;
}
public void run()
{
int x=0;
while(true)
{
if(x==0)
{
b.put("张三",100);
}
else
{
b.put("lisi",200);
}
//0与1之间切换可使用求2的余数
x=(x+1)%2;
}
}
} //定义对象实现Runnable,设置线程任务
class Output implements Runnable
{
private Bank b;
//使用构造函数保证存钱和显示同一资源
public Output(Bank b)
{
this.b=b;
}
public void run()
{
while(true)
{
b.take();
}
}
} class ThreadDemo
{
public static void main (String[] args)
{
//同一资源
Bank b=new Bank(); Input in=new Input(b);
Output out=new Output(b); //
Thread t1=new Thread(in);
Thread t2=new Thread(out); t1.start();
t2.start();
}
}

结果:

出现线程安全,为什么呢?

分析:

解决方法:添加同步(synchronized),同步要添加到什么位置?

添加同步锁的原则:有共享数据被操作的代码上,且同步锁对象要相同(同步方法的同步锁为,此类的对象(this))

代码:

 class Bank
{
String name;//存钱人名
int amount; //同步方法的同步锁为,此类的对象(this)
synchronized void put(String name,int amount)
{
this.name=name;
this.amount=amount;
} synchronized void take()
{
System.out.println(this.name+"---"+this.amount);
}
}

结果出现的效果与预想结果不同,预想结果是存一笔,显示一笔:

结果分析:

接下来,想法是:在t1中执行完成后就让t2执行

具体做法:

1、使用一个共享数据(flag)记录t1是否已执行

2、已执行就让t1等待(原因:防止t1再次获取CPU执行权),让t2执行

3、t2执行完成,t2等待,把t1设置成未执行状态(让t1获取CPU执行资格)

 class Bank
{
private String name;
private int amount;
private boolean flag=false; synchronized void put(String name,int amount)
{
//1、判断线程是否已执行,防止t1线程多次获取CUP执行权
if(flag)
try{this.wait();}catch(InterruptedException e){}//wait()方法,将线程存放在阻塞线程池中,释放CUP执行权和释放同步锁 this.name=name;
this.amount=amount;
//已执行赋值
this.flag = true;
//唤醒阻塞线程池中的任意一个线程,获取CUP执行资格
this.notify();
} synchronized void take()
{
if(!flag)
try{this.wait();}catch(InterruptedException e){}
System.out.println(this.name+"---"+this.amount); this.flag = false;
this.notify();
}
}

结果:

Java学习之线程间通信(双线程)的更多相关文章

  1. 【原】iOS多线程之线程间通信和线程互斥

    线程间通信 1> 线程间通信分为两种 主线程进入子线程(前面的方法都可以) 子线程回到主线程 2> 返回主线程 3> 代码 这个案例的思路是:当我触摸屏幕时,会在子线程加载图片,然后 ...

  2. Java 里如何实现线程间通信

    正常情况下,每个子线程完成各自的任务就可以结束了.不过有的时候,我们希望多个线程协同工作来完成某个任务,这时就涉及到了线程间通信了. 本文涉及到的知识点:thread.join(), object.w ...

  3. Java 如何实现线程间通信

    正常情况下,每个子线程完成各自的任务就可以结束了.不过有的时候,我们希望多个线程协同工作来完成某个任务,这时就涉及到了线程间通信了. 本文涉及到的知识点: thread.join(), object. ...

  4. Java多线程学习(五)线程间通信知识点补充

    系列文章传送门: Java多线程学习(二)synchronized关键字(1) Java多线程学习(二)synchronized关键字(2) Java多线程学习(三)volatile关键字 Java多 ...

  5. 0038 Java学习笔记-多线程-传统线程间通信、Condition、阻塞队列、《疯狂Java讲义 第三版》进程间通信示例代码存在的一个问题

    调用同步锁的wait().notify().notifyAll()进行线程通信 看这个经典的存取款问题,要求两个线程存款,两个线程取款,账户里有余额的时候只能取款,没余额的时候只能存款,存取款金额相同 ...

  6. Java学习:线程间通信

    线程间通信 概念:多个线程在处理同一个资源,但是处理的动作(线程的任务)却不相同重点:有效的利用资源 分析:需要那些类 1 资源类:包子类 设置包子的属性 包子的状态:有true 没有false 2 ...

  7. Java多线程编程(6)--线程间通信(下)

      因为本文的内容大部分是以生产者/消费者模式来进行讲解和举例的,所以在开始学习本文介绍的几种线程间的通信方式之前,我们先来熟悉一下生产者/消费者模式.   在实际的软件开发过程中,经常会碰到如下场景 ...

  8. java线程间通信:一个小Demo完全搞懂

    版权声明:本文出自汪磊的博客,转载请务必注明出处. Java线程系列文章只是自己知识的总结梳理,都是最基础的玩意,已经掌握熟练的可以绕过. 一.从一个小Demo说起 上篇我们聊到了Java多线程的同步 ...

  9. java多线程与线程间通信

    转自(http://blog.csdn.net/jerrying0203/article/details/45563947) 本文学习并总结java多线程与线程间通信的原理和方法,内容涉及java线程 ...

  10. Java多线程——线程间通信

    Java多线系列文章是Java多线程的详解介绍,对多线程还不熟悉的同学可以先去看一下我的这篇博客Java基础系列3:多线程超详细总结,这篇博客从宏观层面介绍了多线程的整体概况,接下来的几篇文章是对多线 ...

随机推荐

  1. vue构造器注册UI组件

    import ConfirmComponent from '../../components/confirm/index' import { mergeOptions } from '../plugi ...

  2. seaborn教程1——风格选择

    原文链接:https://segmentfault.com/a/1190000014915873 Seaborn学习大纲 seaborn的学习内容主要包含以下几个部分: 风格管理 绘图风格设置 颜色风 ...

  3. CSU 1092 Barricade

    1092: Barricade Time Limit: 1 Sec  Memory Limit: 32 MBSubmit: 240  Solved: 71[Submit][Status][Web Bo ...

  4. vue + element 创建教程

    一.环境准备 node安装 node版本:v10.15.3 node下载地址:https://nodejs.org/zh-cn/ vue-cli安装 全局安装vue-cli npm install - ...

  5. Windows 下 MySQL 备份脚本

    @title MySQL备份脚本 @echo off @echo root@127.0.0.1:3306 set host=127.0.0.1 set port=3306 set user=root ...

  6. 靶场练习--sqli(1&2)

    前言 懒猪赵肥肥耍了3天3夜,每天除了练英语口语,啥子都没干.今天开始发愤图强,嘻嘻~ 计划内容有:靶场.视频.python.PHP.java.计算机英语. 首先,每天必搞靶场必看视频必学java和英 ...

  7. 《深入学习Redis(1):Redis内存模型 》笔记,待完善

    参考资料 https://www.cnblogs.com/kismetv/p/8654978.html 一.内存统计 info memory 查看内存统计 五.应用举例

  8. websock(AMQ)通信-前端

    服务端和客户端之间的通信 前端开发经常会依赖后端,那么如果后端服务器还没做好推送服务器,那么前端该如何呢.最简单的就是自己模拟一个服务器,用node来搭建,这边只简单介绍搭建的过程 node搭建服务器 ...

  9. 爬虫技术:scrapy 知识点一

    ---恢复内容开始--- 1.scrapy框架 每一步的解释: step1:引擎从爬虫器获取要爬行的初始请求. step2:引擎在调度程序中调度请求,引擎把这个初始请求传递给调度器,并向调度器索要下一 ...

  10. python实现简单接口

    接口实现 import flask,json server=flask.Flask(__name__)#__name__代表当前的python文件.把当前的python文件当做一个服务启动 @serv ...