java核心知识点学习----多线程间的数据共享的几种实现方式比较
2023-09-14 09:00:18 时间
需求:设计4个线程,其中两个线程每次对j增加1,另外两个线程对j减少1.
实现数据共享的几种方式比较:
1.使用同一个runnable对象
如果每个线程执行的代码相同,那么可以使用同一个runnable对象,这个runnable有那个共享数据,例如,卖票系统就是这么做的.
如下例所示:
... public static void main(String[] args) { ShareData1 shareData1 = new ShareData1(); new Thread(shareData1).start(); new Thread(shareData1).start(); } static class ShareData1 implements Runnable { public int count = 100; public void run() { count--; System.out.println("run:"+count); } } ...
2.使用不同的runnable对象
如果每个线程执行的代码不同,那么要使用不同的runnable对象,有如下两种方式可以实现runnable对象间的数据共享
1).实现两个runnable对象,将共享数据分别传递给两个不同线程.
.... public static void main(String[] args) { final ShareData1 shareData1 = new ShareData1(); new Thread(new MyRunnable1(shareData1)).start(); new Thread(new MyRunnable1(shareData1)).start(); } static class MyRunnable1 implements Runnable{ private ShareData1 shareData1; public void run() { } public MyRunnable1(ShareData1 shareData1){ this.shareData1 = shareData1; } } static class MyRunnable2 implements Runnable{ private ShareData1 shareData1; public void run() { } public MyRunnable2(ShareData1 shareData1){ this.shareData1 = shareData1; } } static class ShareData1 { .... } ......
2).将这些Runnable对象作为一个内部类,将共享数据作为成员变量.
这里用这个方法解决上面的需求,请看下面代码:
package com.amos.concurrent; public class MultiThreadShareData { private int j; public static void main(String[] args) { MultiThreadShareData multiThreadShareData = new MultiThreadShareData(); for(int i=0;i<2;i++){ new Thread(multiThreadShareData.new ShareData1()).start();//增加 new Thread(multiThreadShareData.new ShareData2()).start();//减少 } } //自增 private synchronized void Inc(){ j++; System.out.println(Thread.currentThread().getName()+" inc "+j); } //自减 private synchronized void Dec(){ j--; System.out.println(Thread.currentThread().getName()+" dec "+j); } class ShareData1 implements Runnable { public void run() { for(int i=0;i<5;i++){ Inc(); } } } class ShareData2 implements Runnable { public void run() { for(int i=0;i<5;i++){ Dec(); } } } }
效果:
注:
1.上面的代码,首先,是定义了一个全局的变量j,即共享数据;然后,实现Runnable对象,分别去做自增和自减的操作,然后将实现了的Runnable对象作为一个内部类塞给新建的线程;最后循环两遍,实现两个自减和两个自增线程.
2.这里要注意的是之所以将自增和自减提出来,是为了方便进行线程安全控制.
3.方法二和方法一的区别在于,方法一是主动将共享数据赋给Runnable对象,方法二则是将数据置为全局变量,然后进行操作.
相关文章
- Java反射机制(五):使用反射增强简单工厂设计模式
- [Java基础] java多线程关于消费者和生产者
- JAVA学习(三):Java基础语法(变量、常量、数据类型、运算符与数据类型转换)
- Java实现 LeetCode 784 字母大小写全排列(DFS)
- JVM内幕:Java虚拟机详解
- java核心知识点学习----多线程并发之线程同步
- java多线程 -- ForkJoinPool 分支/ 合并框架 工作窃取
- 【JAVA】 04-Java中的多线程
- linux系统部署Java程序获取ip时报Caused by: java.net.UnknownHostException: XXXXXXXXXX: XXXXXXXXXX: Name or service not known
- 【JAVA】 04-Java中的多线程
- 【JAVA】 01-Java基础知识
- Android面试涨薪攻略指南:Android面试必知必会Java知识点
- Android面试涨薪攻略指南:Android面试的那些高频Java知识点
- 【java】Java经典面试题整理(附答案)
- 【java】Java教程
- Java多线程(全知识点)
- Java面试题之常见十五种异常有哪些?
- Java程序员都要懂得知识点:反射
- java线程知识点拾遗(排队CAS)
- java线程知识点拾遗(1)
- Java如何获取IP属地 ip2region failed to create searcher with x:java.io.FileNotFoundException:( 系统找不到指定的路径)
- JAVA运行java程序
- java代码性能优化总结(转载)
- Java Instrumentation 内存马——主要是利用Instrumentation Java API来做内存注入,会用到反射机制,文中提到检测思路:注入jar包-> dump已加载class字节码->反编译成java代码-> 源码webshell检测
- 基于Java+SpringBoot+Vue前后端分离即时通讯系统设计与实现