iis服务器助手广告广告
返回顶部
首页 > 资讯 > 精选 >Java多线程之间如何共享数据
  • 107
分享到

Java多线程之间如何共享数据

2023-06-25 11:06:34 107人浏览 安东尼
摘要

这篇文章主要介绍Java多线程之间如何共享数据,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!1、线程范围的共享变量多个业务模块针对同一个static变量的操作 要保证在不同线程中 各模块操作的是自身对应的变量对象pu

这篇文章主要介绍Java多线程之间如何共享数据,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!

1、线程范围的共享变量

多个业务模块针对同一个static变量的操作 要保证在不同线程中 各模块操作的是自身对应的变量对象

public class ThreadScopeSharaData {    private static  int data = 0 ;    public static void main(String[] args) {        for(int i = 0 ;i<2 ;i++){            new Thread(new Runnable(){                @Override                public void run() {                    data = new Random().nextInt();                    System.out.println(Thread.currentThread().getName()+ " put random data:"+data);                    new A().get() ;                    new B().get() ;                }            }).start() ;        }    }    static class A {        public int get(){            System.out.println("A from " + Thread.currentThread().getName()                    + " get data :" + data);            return data ;        }    }    static class B{        public int get(){            System.out.println("B from " + Thread.currentThread().getName()                    + " get data :" + data);            return data ;        }    }}

模块A ,B都需要访问static的变量data 在线程0中会随机生成一个data值 假设为10 那么此时模块A和模块B在线程0中得到的data的值为10 ;在线程1中 假设会为data赋值为20 那么在当前线程下

模块A和模块B得到data的值应该为20

看程序执行的结果:

Thread-0 put random data:-2009009251
Thread-1 put random data:-2009009251
A from Thread-0 get data :-2009009251
A from Thread-1 get data :-2009009251
B from Thread-0 get data :-2009009251
B from Thread-1 get data :-2009009251


Thread-0 put random data:-2045829602
Thread-1 put random data:-1842611697
A from Thread-0 get data :-1842611697
A from Thread-1 get data :-1842611697
B from Thread-0 get data :-1842611697
B from Thread-1 get data :-1842611697

会出现两种情况:

  • 由于线程执行速度,新的随机值将就的随机值覆盖 data 值一样

  • data 值不一样,但 A、B线程都

2、使用Map实现线程范围内数据的共享

可是将data数据和当前允许的线程绑定在一块,在模块A和模块B去获取数据data的时候 是通过当前所属的线程去取得data的结果就行了。
声明一个Map集合 集合的Key为Thread 存储当前所属线程 Value 保存data的值,

代码如下:

public class ThreadScopeSharaData {    private static Map<Thread, Integer> threadData = new HashMap<>();    public static void main(String[] args) {        for (int i = 0; i < 2; i++) {            new Thread(new Runnable() {                @Override                public void run() {                    int data = new Random().nextInt();                    System.out.println(Thread.currentThread().getName() + " put random data:" + data);                    threadData.put(Thread.currentThread(), data);                    new A().get();                    new B().get();                }            }).start();        }    }    static class A {        public void get() {            int data = threadData.get(Thread.currentThread());            System.out.println("A from " + Thread.currentThread().getName() + " get data:" + data);        }    }    static class B {        public void get() {            int data = threadData.get(Thread.currentThread());            System.out.println("B from " + Thread.currentThread().getName() + " get data:" + data);        }    }}

Thread-0 put random data:-123490895
Thread-1 put random data:-1060992440
A from Thread-0 get data:-123490895
A from Thread-1 get data:-1060992440
B from Thread-0 get data:-123490895
B from Thread-1 get data:-1060992440

Java多线程之间如何共享数据

3、ThreadLocal实现线程范围内数据的共享

(1)订单处理包含一系列操作:减少库存量、增加一条流水台账、修改总账,这几个操作要在同一个事务中完成,通常也即同一个线程中进行处理,如果累加公司应收款的操作失败了,则应该把前面的操作回滚,否则,提交所有操作,这要求这些操作使用相同的数据库连接对象,而这些操作的代码分别位于不同的模块类中。

(2)银行转账包含一系列操作: 把转出帐户的余额减少,把转入帐户的余额增加,这两个操作要在同一个事务中完成,它们必须使用相同的数据库连接对象,转入和转出操作的代码分别是两个不同的帐户对象的方法。

(3)例如Strut2ActionContext,同一段代码被不同的线程调用运行时,该代码操作的数据是每个线程各自的状态和数据,对于不同的线程来说,getContext方法拿到的对象都不相同,对同一个线程来说,不管调用getContext方法多少次和在哪个模块中getContext方法,拿到的都是同一个。

(4)实验案例:定义一个全局共享的ThreadLocal变量,然后启动多个线程向该ThreadLocal变量中存储一个随机值,接着各个线程调用另外其他多个类的方法,这多个类的方法中读取这个ThreadLocal变量的值,就可以看到多个类在同一个线程中共享同一份数据。

(5)实现对ThreadLocal变量的封装,让外界不要直接操作ThreadLocal变量。

  • 对基本类型的数据的封装,这种应用相对很少见。

  • 对对象类型的数据的封装,比较常见,即让某个类针对不同线程分别创建一个独立的实例对象。

public class ThreadLocalTest {    private static ThreadLocal<Integer> threadLocal = new ThreadLocal<>();    public static void main(String[] args) {        for (int i = 0; i < 2; i++) {            new Thread(new Runnable() {                @Override                public void run() {                    int data = new Random().nextInt();                    System.out.println(Thread.currentThread().getName() + " put random data:" + data);                    threadLocal.set(data);                    new A().get();                    new B().get();                }            }).start();        }    }    static class A {        public void get() {            int data = threadLocal.get();            System.out.println("A from " + Thread.currentThread().getName() + " get data:" + data);        }    }    static class B {        public void get() {            int data = threadLocal.get();            System.out.println("B from " + Thread.currentThread().getName() + " get data:" + data);        }    }}

Thread-0 put random data:-2015900409
Thread-1 put random data:-645411160
A from Thread-0 get data:-2015900409
A from Thread-1 get data:-645411160
B from Thread-0 get data:-2015900409
B from Thread-1 get data:-645411160

4、优化

public class ThreadLocalTest {    private static ThreadLocal<Integer> threadLocal = new ThreadLocal<>();    //private static ThreadLocal<MyThreadScopeData> myThreadScopeDataThreadLocal = new ThreadLocal<>();    public static void main(String[] args) {        for (int i = 0; i < 2; i++) {            new Thread(new Runnable() {                @Override                public void run() {                    int data = new Random().nextInt();                    System.out.println(Thread.currentThread().getName() + " put random data:" + data);                    threadLocal.set(data);//                    MyThreadScopeData myThreadScopeData = new MyThreadScopeData();//                    myThreadScopeData.setName("name" + data);//                    myThreadScopeData.setAge(data);//                    myThreadScopeDataThreadLocal.set(myThreadScopeData);                    //获取与当前线程绑定的实例并设置值                      MyThreadScopeData.getThreadInstance().setName("name" + data);                    MyThreadScopeData.getThreadInstance().setAge(data);                    new A().get();                    new B().get();                }            }).start();        }    }    static class A {        public void get() {            int data = threadLocal.get();//            MyThreadScopeData myData = myThreadScopeDataThreadLocal.get();//////            System.out.println("A from " + Thread.currentThread().getName()//                    + " getMyData: " + myData.getName() + "," + myData.getAge());            MyThreadScopeData myData = MyThreadScopeData.getThreadInstance();            System.out.println("A from " + Thread.currentThread().getName()                    + " getMyData: " + myData.getName() + "," + myData.getAge());        }    }    static class B {        public void get() {            int data = threadLocal.get();            //System.out.println("B from " + Thread.currentThread().getName() + " get data:" + data);            MyThreadScopeData myData = MyThreadScopeData.getThreadInstance();            System.out.println("B from " + Thread.currentThread().getName()                    + " getMyData: " + myData.getName() + "," + myData.getAge());        }    }}//一个绑定当前线程的类class MyThreadScopeData {    private static ThreadLocal<MyThreadScopeData> map = new ThreadLocal<>();    private String name;    private int age;    private MyThreadScopeData() {    }    //定义一个静态方法,返回各线程自己的实例    //这里不必用同步,因为每个线程都要创建自己的实例,所以没有线程安全问题。    public static MyThreadScopeData getThreadInstance() {        //获取当前线程绑定的实例        MyThreadScopeData instance = map.get();        if (instance == null) {            instance = new MyThreadScopeData();            map.set(instance);        }        return instance;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public int getAge() {        return age;    }    public void setAge(int age) {        this.age = age;    }}

Thread-1 put random data:-1041517189
Thread-0 put random data:-98835751
A from Thread-1 getMyData: name-1041517189,-1041517189
A from Thread-0 getMyData: name-98835751,-98835751
B from Thread-1 getMyData: name-1041517189,-1041517189
B from Thread-0 getMyData: name-98835751,-98835751

5、实例

设计4个线程,其中两个线程每次对j增加1,另外两个线程对j每次减少1,写出程序。

(1)如果每个线程执行的代码相同,可以使用同一个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;    public synchronized void run() {        while (ticket > 0) {            ticket--;            System.out.println("当前票数为:" + ticket);        }    }}

(2)如果每个线程执行的代码不同,这时候需要用不同的Runnable对象,例如,设计2个线程。一个线程对j增加1,另外一个线程对j减1,银行存取款系统。

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();            }        }    }}

Thread-0 inc 1
Thread-0 inc 2
Thread-0 inc 3
Thread-0 inc 4
Thread-0 inc 5
Thread-1 dec 4
Thread-1 dec 3
Thread-2 inc 4
Thread-2 inc 5
Thread-2 inc 6
Thread-2 inc 7
Thread-2 inc 8
Thread-1 dec 7
Thread-1 dec 6
Thread-1 dec 5
Thread-3 dec 4
Thread-3 dec 3
Thread-3 dec 2
Thread-3 dec 1
Thread-3 dec 0

以上是“Java多线程之间如何共享数据”这篇文章的所有内容,感谢各位的阅读!希望分享的内容对大家有帮助,更多相关知识,欢迎关注编程网精选频道!

--结束END--

本文标题: Java多线程之间如何共享数据

本文链接: https://www.lsjlt.com/news/304168.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Java多线程之间如何共享数据
    这篇文章主要介绍Java多线程之间如何共享数据,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!1、线程范围的共享变量多个业务模块针对同一个static变量的操作 要保证在不同线程中 各模块操作的是自身对应的变量对象pu...
    99+
    2023-06-25
  • Java 多线程之间共享数据
    目录1、线程范围的共享变量2、使用Map实现线程范围内数据的共享3、ThreadLocal实现线程范围内数据的共享4、优化5、实例1、线程范围的共享变量 多个业务模块针对同一个sta...
    99+
    2024-04-02
  • Java如何实现多个线程之间共享数据
    目录实现多个线程之间共享数据一、 如果每个线程执行的代码相同二、 如果每个线程执行的代码不同多线程之间共享数据的方式探讨方式一:代码一致方式二:代码不一致实现多个线程之间共享数据 一...
    99+
    2024-04-02
  • C++多线程编程之如何解决多线程数据共享问题
    这篇文章主要讲解了“C++多线程编程之如何解决多线程数据共享问题”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“C++多线程编程之如何解决多线程数据共享问题”吧!通过容器创建多个线程#incl...
    99+
    2023-06-15
  • Python 多进程 多线程数据共享
    #!/usr/bin/env python # -*- coding:utf-8 -*- # author: Changhua Gong from multiprocessing import Process, Queue import o...
    99+
    2023-01-31
    多线程 进程 数据
  • Java线程之间的共享与协作详解
    目录前言一、进程和线程1、进程是程序运行资源分配的最小单位2、线程是CPU 调度的最小单位,必须依赖于进程而存在3、线程无处不在二、CPU 核心数和线程数的关系1、多核心2、多线程3...
    99+
    2024-04-02
  • Java并发编程之线程之间的共享和协作
    目录一、线程间的共享1.1 ynchronized内置锁1.2 volatile关键字1.3 ThreadLocal1.4 Spring的事务借助ThreadLocal类1.4.1 ...
    99+
    2024-04-02
  • Java线程之间的共享与协作是什么
    这篇文章主要讲解了“Java线程之间的共享与协作是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Java线程之间的共享与协作是什么”吧!一、进程和线程1、进程是程序运行资源分配的最小单位...
    99+
    2023-07-02
  • 如何在多个应用之间共享和传输Hadoop数据
    要在多个应用之间共享和传输Hadoop数据,可以使用以下几种方法: 使用Hadoop的HDFS(Hadoop分布式文件系统)来存...
    99+
    2024-02-29
    Hadoop
  • 【Java】线程数据共享和安全 -ThreadLocal
     🎄欢迎来到@边境矢梦°的csdn博文🎄  🎄本文主要梳理线程数据共享和安全 -ThreadLocal🎄 🌈我是边境矢梦°,一个正在为秋招和算法竞赛做...
    99+
    2023-09-08
    java 开发语言 ThreadLocal servlet tomcat javascript
  • python多线程数据共享怎么实现
    在Python中,可以使用`threading`模块来实现多线程数据共享。具体步骤如下: 导入`threading`模块:`im...
    99+
    2023-10-26
    python
  • 微信小程序如何实现在画面之间共享数据
    这篇文章主要介绍“微信小程序如何实现在画面之间共享数据”,在日常操作中,相信很多人在微信小程序如何实现在画面之间共享数据问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”微信小程序如何实现在画面之间共享数据”的疑...
    99+
    2023-06-19
  • python多线程数据共享的方法是什么
    Python中多线程数据共享的方法有以下几种:1. 全局变量:在多个线程中使用全局变量进行数据共享。但是需要注意的是,全局变量在多线...
    99+
    2023-08-12
    python
  • Java中怎么利用多线程锁实现数据同步共享
    Java中怎么利用多线程锁实现数据同步共享,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。大多数应用程序要求线程互相通信来同步它们的动作。在Java程序中最简单实现同步的方法就是...
    99+
    2023-06-17
  • 使用Java怎么实现线程之间的共享和协作
    这篇文章将为大家详细讲解有关使用Java怎么实现线程之间的共享和协作,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。一、线程间的共享1.1 ynchronized内置锁用处Java支持多个线程...
    99+
    2023-06-14
  • php如何实现不同域名之间的数据共享
    在当前的Web开发环境中,不同的应用程序运行在不同的域名之下,这就导致了不同域名的应用程序之间无法直接共享数据。在这种情况下,如何实现不同域名之间的数据共享呢?本文将会介绍一种基于PHP的解决方案。一、前端跨域在当前的Web开发环境中,“跨...
    99+
    2023-05-14
    php
  • Vue组件之间的数据共享详解
    目录一、在项目开发中,组件之间的最常见的关系分为如下两种:1.1父子组件之间的数据共享1. 父->子共享数据2.子->父共享数据1.2兄弟组件之间的数据共享总结一、在项目...
    99+
    2024-04-02
  • Java线程间共享与协作详细介绍
    目录线程的共享synchronized内置锁错误的加锁和原因分析volatile,最轻量的同步机制ThreadLocal与 Synchonized的比较ThreadLocal的使用实...
    99+
    2024-04-02
  • java多个线程怎么共享一个变量
    Java中多个线程可以通过共享变量来实现线程之间的通信和共享数据。以下是几种常见的实现方式: 使用共享变量作为实例变量:将共享变量...
    99+
    2023-10-27
    java
  • Python线程之如何解决共享变量问题
    前面提到了银行转账这个场景,展示了一个比较耗时的转账操作。 这篇继续转帐,下面展示一段程序,多个线程的操作都更改了amount变量导致运行结果不对的问题。 前文说了转账问题 下面展示...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作