当前位置: 首页 > news >正文

java并发编程之:线程共享数据的方式

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

java并发编程之:线程共享数据的方式

多个线程对共同数据的访问的实现,要根据情况而定

(1)当访问共同的代码的时候:可以使用同一个Runnable对象,这个Runnable对象中有这个共享数据,比如卖*系统就可以这么做。或者这个共享数据封装在一个对象当中,然后对这个对象加锁,也可以实现数据安全访问。

(2)当各个线程访问的代码不同时:这时候要使用不同的Runnable对象,有两种实现方式:

a)将共享数据封装在另一个对象当中,然后将这个对象逐一的转递给各个Runnable对象。操作数据的方法也放进这个对象当中。这样容易实现各个线程对这个数据的同步和共享。

b)将Runnable对象作为某一个类中的内部类,共享数据作为这个外部类的成员变量,每个线程对共享数据的访问也交给外部类的方法,比便对共享数据的互斥和通信。Runnable对象调用外部类的操作这个共享数据的方法。

还有一种方式是a)和b)的结合实现,把共享数据封装到一个对象当中去,这个对象也实现对这个共享数据的操作,这个对象作为外部类的成员变量。然后再创建多个Runnable对象做为内部类,操作这个对象。

一、每个线程执行的代码相同,可以使用同一个Runnable对象

public class SellTicket {

    public static void main(String[] args) {
        Ticket t = new Ticket();
        new Thread(t).start();
        new Thread(t).start();
    }

}
class Ticket implements Runnable{
    private int ticket = 10;
    @Override
    public void  run() {
        while(ticket>0){
            synchronized (this){
                if(ticket > 0){
                    ticket--;
                    System.out.println("当前*数为:"+ticket);
                }
            }
        }
    }
}

二 1)当各个线程访问的代码不同时:这时候要使用不同的Runnable对象,将共享数据封装在另一个对象当中,然后将这个对象逐一的转递给各个Runnable对象。操作数据的方法也放进这个对象当中。这样容易实现各个线程对这个数据的同步和共享

public class MultiThreadShareData {
	public static void main(String[] args) {
		ShareData1 data2 = new ShareData1();
		new Thread(new MyRunnable1(data2)).start();
		new Thread(new MyRunnable2(data2)).start();
	}
}
	
	class MyRunnable1 implements Runnable{
		private ShareData1 data1;
		public MyRunnable1(ShareData1 data1){
			this.data1 = data1;
		}
		public void run() {
			data1.decrement();
			
		}
	}
	
	class MyRunnable2 implements Runnable{
		private ShareData1 data1;
		public MyRunnable2(ShareData1 data1){
			this.data1 = data1;
		}
		public void run() {
			data1.increment();
		}
	}

	class ShareData1 {
		private int j = 0;
		public synchronized void increment(){
			j++;
		}
		
		public synchronized void decrement(){
			j--;
		}
	}

二 2)把共享数据封装到一个对象当中去,这个对象也实现对这个共享数据的操作,这个对象作为外部类的成员变量。然后再创建多个Runnable对象做为内部类,操作这个对象

public class MultiThreadShareData {
	public static void main(String[] args) {
		final ShareData1 data1 = new ShareData1();//现在为局部变量,也可以写成类变量static类型(在main方法外声明)
		new Thread(new Runnable(){
			@Override
			public void run() {
				data1.decrement();

			}
		}).start();
		new Thread(new Runnable(){
			@Override
			public void run() {
				data1.increment();

			}
		}).start();
	}
}
	
	class MyRunnable1 implements Runnable{
		private ShareData1 data1;
		public MyRunnable1(ShareData1 data1){
			this.data1 = data1;
		}
		public void run() {
			data1.decrement();
			
		}
	}
	
	class MyRunnable2 implements Runnable{
		private ShareData1 data1;
		public MyRunnable2(ShareData1 data1){
			this.data1 = data1;
		}
		public void run() {
			data1.increment();
		}
	}

	class ShareData1 {
		private int j = 0;
		public synchronized void increment(){
			j++;
		}
		
		public synchronized void decrement(){
			j--;
		}
	}

总结:对于要是下同步互斥的代码要放在不同的方法中,并且放在同一个对象当中,容易实现互斥和通信,并且也有利于日后的维护。这样思路也很清晰。

 

多线程间进行通讯例子:(wait(),notify())

public class TraditionalThreadCommunication {
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		
		final Business business = new Business();
		new Thread(
				new Runnable() {
					
					@Override
					public void run() {
						for(int i=1;i<=20;i++){
							business.sub(i);
						}
					}
				}
		).start();
		for(int i=1;i<=20;i++){
			business.main(i);
		}
	}

}
  class Business {
	  private boolean bShouldSub = true;
	  public synchronized void sub(int i){
		  while(!bShouldSub){//建议用while 因为线程有时候会被假唤醒,线程没有被通知的时候被唤醒
			  try {
				this.wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		  }
			for(int j=1;j<=10;j++){
				System.out.println("sub thread sequence of " + j + ",loop of " + i);
			}
		  bShouldSub = false;
		  this.notify();
	  }
	  
	  public synchronized void main(int i){
		  	while(bShouldSub){
		  		try {
					this.wait();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
		  	}
			for(int j=1;j<=100;j++){
				System.out.println("main thread sequence of " + j + ",loop of " + i);
			}
			bShouldSub = true;
			this.notify();
	  }
  }

锁是上在代表要操作的资源的类内部方法中的,而不是线程代码中的。

synchronized 锁什么对象,wait 和 notify 就作用在什么对象上。否则会报错。

 

 

 

转载于:https://my.oschina.net/LucasZhu/blog/1023387

相关文章:

  • 《2017年全球数据库安全市场趋势》
  • 聊聊运维(1)证明你是坏运维的七个迹象,不要做CPR运维
  • 怎样制作C#安装程序
  • Sqoop_具体总结 使用Sqoop将HDFS/Hive/HBase与MySQL/Oracle中的数据相互导入、导出
  • [UWP]了解模板化控件(6):使用附加属性
  • 新公司,新挑战
  • linux: 进程管理常用指令
  • RabbitMQ6种常用业务场景分析
  • 面试题——敲代码推断操作系统位数
  • FetchType与FetchMode的差别
  • 4443: [Scoi2015]小秃玩矩阵|二分答案|匈牙利
  • OPENGL 红宝书实验笔记
  • 智能家居新品迭出 巨头涌入加速产业升级
  • 不谈营收的 SaaS 增长都是耍流氓!
  • “云上贵州”大赛完整诠释大数据三大业态
  • 时间复杂度分析经典问题——最大子序列和
  • “寒冬”下的金三银四跳槽季来了,帮你客观分析一下局面
  • 【162天】黑马程序员27天视频学习笔记【Day02-上】
  • 0x05 Python数据分析,Anaconda八斩刀
  • canvas 绘制双线技巧
  • CentOS从零开始部署Nodejs项目
  • CSS盒模型深入
  • django开发-定时任务的使用
  • docker容器内的网络抓包
  • in typeof instanceof ===这些运算符有什么作用
  • isset在php5.6-和php7.0+的一些差异
  • Java 实战开发之spring、logback配置及chrome开发神器(六)
  • JS创建对象模式及其对象原型链探究(一):Object模式
  • js如何打印object对象
  • mac修复ab及siege安装
  • Node项目之评分系统(二)- 数据库设计
  • Puppeteer:浏览器控制器
  • ReactNativeweexDeviceOne对比
  • vue 配置sass、scss全局变量
  • Vultr 教程目录
  • 回顾 Swift 多平台移植进度 #2
  • 回流、重绘及其优化
  • 机器人定位导航技术 激光SLAM与视觉SLAM谁更胜一筹?
  • 前端之Sass/Scss实战笔记
  • 手写一个CommonJS打包工具(一)
  • 微服务框架lagom
  • 用Node EJS写一个爬虫脚本每天定时给心爱的她发一封暖心邮件
  • 正则表达式小结
  • ionic异常记录
  • MyCAT水平分库
  • Nginx惊现漏洞 百万网站面临“拖库”风险
  • ​ssh-keyscan命令--Linux命令应用大词典729个命令解读
  • ###STL(标准模板库)
  • #stm32驱动外设模块总结w5500模块
  • #中国IT界的第一本漂流日记 传递IT正能量# 【分享得“IT漂友”勋章】
  • (1/2) 为了理解 UWP 的启动流程,我从零开始创建了一个 UWP 程序
  • (html转换)StringEscapeUtils类的转义与反转义方法
  • (JSP)EL——优化登录界面,获取对象,获取数据
  • (Matalb分类预测)GA-BP遗传算法优化BP神经网络的多维分类预测
  • (Redis使用系列) Springboot 使用redis实现接口Api限流 十