java多线程信息共享
上篇文章知识介绍了多线程的创建和启动问题,各个子线程和子线程或者说子线程和main线程没有信息的交流,这篇文章主要探讨线程之间信息共享以及交换问题。这篇文章主要以一个卖票例子来展开。
继承Thread重写run方法进行实现
初始代码:
public class Tickect1 {
public static void main(String[] args) {
//创建四个线程进行测试
new Thread3().start();
new Thread3().start();
new Thread3().start();
new Thread3().start();
}
}
class Thread3 extends Thread{
private static int tickets = 100;//总票数
@Override
public void run() {
while(true){
if(tickets<=0){
break;
}else{
System.out.println(Thread.currentThread().getName()+" "+tickets);
tickets--;
}
}
}
}
错误答案:卖了103张票

分析原因:1.类似于i++的操作不是原子操作


四个进程有四个工作缓存,每次都是修改工作缓存的数据,而且四个工作缓存之间的数据无法共享,倒置在缓存1中已经tickets-1,但是缓存2中tickets又无法获取1中缓存的数据所以票会增大,所以出现103
2.关键步骤缺少加锁操作(获取票数和对票数-1的操作同时执行会出现问题)


改进的代码:这个代码有bug,测试答案还是103
public class Tickect1 {
public static void main(String[] args) {
//创建四个线程进行测试
new Thread3().start();
new Thread3().start();
new Thread3().start();
new Thread3().start();
}
}
class Thread3 extends Thread{
private static volatile int tickets = 100;//总票数
@Override
public void run() {
while(true){
sale();
if(tickets<=0) break;
}
}
public synchronized void sale(){//对数据修改进行加锁(同一时刻只能一个线程执行)
if(tickets>0){
System.out.println(Thread.currentThread().getName()+" "+tickets);
tickets--;
}
}
}
实现Runnable的run方法进行实现
public class Ticket2 {
public static void main(String[] args) {
Thread4 t = new Thread4();
new Thread(t).start();
new Thread(t).start();
new Thread(t).start();
new Thread(t).start();
}
}
class Thread4 implements Runnable{
private volatile int tickets=100;//volatile起到通知各个线程缓存区的数据是否修改,如果修改就刷新缓冲区数据(变量副本的解决方法)
String str = new String("");//对这个对象加锁
@Override
public void run() {
while (true){
//sale();方式1
synchronized (str){//代码快加锁(方式2)
if(tickets>0){
System.out.println(Thread.currentThread().getName()+" "+tickets);
tickets--;
}
}
if(tickets<=0) break;
}
}
public synchronized void sale(){//synchronized对数据修改进行加锁(同一时刻只能一个线程执行)
if(tickets>0){//必须在这里判断,if放在外面会出现错误
System.out.println(Thread.currentThread().getName()+" "+tickets);
tickets--;
}
}
}

volatile关键字测试
public class ThreadDemo2
{
public static void main(String args[]) throws Exception
{
TestThread2 t = new TestThread2();
t.start();
Thread.sleep(2000);
t.flag = false;
System.out.println("main thread is exiting");
}
}
class TestThread2 extends Thread
{
//boolean flag = true; //子线程不会停止
volatile boolean flag = true; //用volatile修饰的变量可以及时在各线程里面通知
public void run()
{
int i=0;
while(flag)
{
i++;
}
System.out.println("test thread3 is exiting");
}
}
java多线程信息共享的更多相关文章
- JAVA多线程之间共享数据BlockingQueue介绍
在JAVA的Concurrent包中,BlockingQueue很好的解决了多线程中,如何高效安全“传输”数据的问题.通过这些高效并且线程安全的队列类,为我们快速搭建高质量的多线程程序带来极大的便利. ...
- java——多线程——内部类共享同一个外部类对象的成员变量
public class Shop { public static void main(String[] args) { Outer o=new Outer(); Thread t1=o.getSal ...
- 循序渐进Java Socket网络编程(多客户端、信息共享、文件传输)
目录[-] 一.TCP/IP协议 二.TCP与UDP 三.Socket是什么 四.Java中的Socket 五.基本的Client/Server程序 六.多客户端连接服务器 七.信息共享 八.文件传输 ...
- JAVA Socket(多个客户同时连接,信息共享) client (java/ruby)
第一步 充分理解Socket 1.什么是socket 所谓socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄.应用程序通常通过"套接字" ...
- Java多线程调试如何完成信息输出处理
转载自:http://developer.51cto.com/art/201003/189078.htm Java多线程调试是很繁琐的,但是还是需要我们不断进行相关的学习.下面我们就来看看在Java多 ...
- Java多线程——查看线程堆栈信息
Java多线程——查看线程堆栈信息 摘要:本文主要介绍了查看线程堆栈信息的方法. 使用Thread类的getAllStackTraces()方法 方法定义 可以看到getAllStackTraces( ...
- 40个Java多线程问题总结
前言 Java多线程分类中写了21篇多线程的文章,21篇文章的内容很多,个人认为,学习,内容越多.越杂的知识,越需要进行深刻的总结,这样才能记忆深刻,将知识变成自己的.这篇文章主要是对多线程的问题进行 ...
- Java多线程干货系列—(一)Java多线程基础
前言 多线程并发编程是Java编程中重要的一块内容,也是面试重点覆盖区域,所以学好多线程并发编程对我们来说极其重要,下面跟我一起开启本次的学习之旅吧. 正文 线程与进程 1 线程:进程中负责程序执行的 ...
- Java多线程系列--“JUC锁”08之 共享锁和ReentrantReadWriteLock
概要 Java的JUC(java.util.concurrent)包中的锁包括"独占锁"和"共享锁".在“Java多线程系列--“JUC锁”02之 互斥锁Ree ...
随机推荐
- 2019-08-10 纪中NOIP模拟B组
T1 [JZOJ1235] 洪水 题目描述 一天, 一个画家在森林里写生,突然爆发了山洪,他需要尽快返回住所中,那里是安全的. 森林的地图由R行C列组成,空白区域用点“.”表示,洪水的区域用“*”表示 ...
- 3ds Max File Format (Part 2: The first inner structures; DllDirectory, ClassDirectory3)
Now that we understand the outer structure of the file, it's time to look closer to what's inside. T ...
- 基于alpine的php-fpm扩展swoole和pdo_mysql
vim Dockerfile 插入一下内容 FROM php:fpm-alpine RUN echo http://mirrors.aliyun.com/alpine/v3.10/main>/e ...
- 【转】常见的hash算法及其原理
Hash,一般翻译做“散列”,也有直接音译为“哈希”的,就是把任意长度的输入(又叫做预映射, pre-image),通过散列算法,变换成固定长度的输出,该输出就是散列值.这种转换是一种压缩映射,也就是 ...
- Echart 地图实例
1.地图实例 function func_InEchart() { require.config({ paths: { echarts: '../Scripts/echart2/echarts' }, ...
- PP: Composite visual mapping for time series visualization
However: The conventional visual mapping maps each data attribute onto a single visual channel Purpo ...
- POJ3258 River Hopscotch(二分最大化最小值)
题目链接:http://poj.org/problem?id=3258 题意:给n个石头,起点和终点也是两个石头,去掉这石头中的m个,使得石头间距的最小值最大. 思路:二分石头间的最短距离,每次贪心地 ...
- leetcode 925. Long Pressed Name
判定是否长按 var isLongPressedName = function (name, typed) { var i = 1, j = 0, n = name.length, m = typed ...
- android 获取颜色 getColor 方法 deprecated 过期
可以使用下面代码代替: ContextCompat.getColor(getContext(), R.color.post_list_content_color) 需要引入: compile 'com ...
- bitlocker对磁盘进行加密解密
1,bitlocker是什么? BitLocker即Windows BitLocker驱动器加密.是微软在Windows Vista中新增的一种数据保护功能.使用BitLocker可以加密磁盘.主要用 ...