线程间共享数据

简介:

一、每个线程执行的代码相同

若每个线程执行的代码相同,共享数据就比较方便。可以使用同一个Runnable对象,这个Runnable对象中就有那个共享数据。

public class MultiThreadShareData1
{
public static void main(String[] args)
{
 SaleTickets sale = new SaleTickets();
 new Thread(sale).start();
 new Thread(sale).start();
}
}

class SaleTickets implements Runnable
{
public int allTicketCount = 20;

public void run()
{
 while (allTicketCount > 0)
 {
  sale();
 }
}

public synchronized void sale()
{
 System.out.println("
剩下" + allTicketCount);
 allTicketCount--;
}
}
SaleTickets这个对象中就有需要共享的数据allTicketCount,两个线程使用同一个SaleTickets,就可以共享allTicketCount了。


二、每个线程执行的代码不相同
方法1:将需要共享的数据封装成一个对象,将该对象传给执行不同代码的Runnable对象。
方法2:将这些执行不同代码的Runnable对象作为内部类。
看例子:有4个线程,其中有2个线程对每次对j+1,有2个线程对每次对j-1。加减操作无顺序。

方法1:
public class MultiThreadShareData3
{
public static void main(String[] args)
{
int j = 10;
NumberInfo nInfo = new NumberInfo(j);
 for (int i = 0; i < 2; i++)
 {
  new Thread(new NumberInfoAdd("增线程", nInfo)).start();
  new Thread(new NumberInfoMinus("减线程", nInfo)).start();
 }
}
}

class NumberInfo
{
private int number;

public NumberInfo(int number)
{
 this.number = number;
}

public int getNumber()
{
 return number;
}

public void setNumber(int number)
{
 this.number = number;
}

public void add()
{
 System.out.println("
数值:" + (++number));
}

public void minus()
{
 System.out.println("
数值:" + (--number));
}
}

//增操作
class NumberInfoAdd implements Runnable
{
private String name;
private NumberInfo nInfo;

public NumberInfoAdd(String name, NumberInfo nInfo)
{
 this.name = name;
 this.nInfo = nInfo;
}

public void run()
{
 add();
}

public void add()
{
synchronized (nInfo)
 {
  System.out.print(name + "--");
  nInfo.add();
 }
}
}

//减操作
class NumberInfoMinus implements Runnable
{
private String name;
private NumberInfo nInfo;

public NumberInfoMinus(String name, NumberInfo nInfo)
{
 this.name = name;
 this.nInfo = nInfo;
}

public void run()
{
 minus();
}

public void minus()
{
synchronized (nInfo)
 {
  System.out.print(name + "--");
  nInfo.minus();
 }
}
}


方法2:
public class MultiThreadShareData4
{
int j = 10;
public static void main(String[] args)
{
 MultiThreadShareData4 m = new MultiThreadShareData4();
 for (int i = 0; i < 2; i++)
 {
  new Thread(m.new NumberInfoAdd()).start();
  new Thread(m.new NumberInfoMinus()).start();
 }
}

public synchronized void add()
{
 System.out.println("
增加后数值:" + (++j));
}

public synchronized void minus()
{
 System.out.println("
減少后数值:" + (--j));
}

//
class NumberInfoAdd implements Runnable
{
 public void run()
 {
  add();
 }
}

//
class NumberInfoMinus implements Runnable
{
 public void run()
 {
  minus();
 }
}
}

执行结果可能是:

增线程--数值:11
增线程--数值:12
减线程--数值:11
减线程--数值:10

执行结果也可能是:
增线程--数值:11
减线程--数值:10
减线程--数值:9
增线程--数值:10

其实线程执行相同代码也可以按照这些方法来做,看一个方法1:

public class MultiThreadShareData2
{
public static void main(String[] args)
{
 TicketInfo tInfo = new TicketInfo(20);
 new Thread(new SaleTickets2("
线程1", tInfo)).start();
 new Thread(new SaleTickets2("线程2", tInfo)).start();
}
}

class TicketInfo
{
private int allTicketCount;

public TicketInfo(int allTicketCount)
{
 this.allTicketCount = allTicketCount;
}

public int getAllTicketCount()
{
 return allTicketCount;
}

public void setAllTicketCount(int allTicketCount)
{
 this.allTicketCount = allTicketCount;
}

public void sale()
{
 System.out.println("
剩余:" + allTicketCount--);
}
}

class SaleTickets2 implements Runnable
{
private String name;
private TicketInfo tInfo;

public SaleTickets2(String name, TicketInfo tInfo)
{
 this.name = name;
 this.tInfo = tInfo;
}

public void run()
{
 while (tInfo.getAllTicketCount() > 0)
 {
  sale();
 }
}

public void sale()
{
 synchronized (tInfo)
 {
  System.out.print(name + "--");
  tInfo.sale();
 }
}
}

部分代码参考张孝祥老师线程视频源码。

本文转自IT徐胖子的专栏博客51CTO博客,原文链接http://blog.51cto.com/woshixy/1357027如需转载请自行联系原作者


woshixuye111

相关文章
|
8月前
|
Java 索引
多线程向设备发送数据
多线程向设备发送数据
141 0
|
5月前
|
设计模式 缓存 安全
【JUC】(6)带你了解共享模型之 享元和不可变 模型并初步带你了解并发工具 线程池Pool,文章内还有饥饿问题、设计模式之工作线程的解决于实现
JUC专栏第六篇,本文带你了解两个共享模型:享元和不可变 模型,并初步带你了解并发工具 线程池Pool,文章中还有解决饥饿问题、设计模式之工作线程的实现
326 2
|
8月前
|
数据采集 监控 调度
干货分享“用 多线程 爬取数据”:单线程 + 协程的效率反超 3 倍,这才是 Python 异步的正确打开方式
在 Python 爬虫中,多线程因 GIL 和切换开销效率低下,而协程通过用户态调度实现高并发,大幅提升爬取效率。本文详解协程原理、实战对比多线程性能,并提供最佳实践,助你掌握异步爬虫核心技术。
|
消息中间件 监控 安全
服务Down机了,线程池中的数据如何保证不丢失?
在分布式系统与高并发应用开发中,服务的稳定性和数据的持久性是两个至关重要的考量点。当服务遭遇Down机时,如何确保线程池中处理的数据不丢失,是每一位开发者都需要深入思考的问题。以下,我将从几个关键方面分享如何在这种情况下保障数据的安全与完整性。
364 2
|
消息中间件 监控 Java
线程池关闭时未完成的任务如何保证数据的一致性?
保证线程池关闭时未完成任务的数据一致性需要综合运用多种方法和机制。通过备份与恢复、事务管理、任务状态记录与恢复、数据同步与协调、错误处理与补偿、监控与预警等手段的结合,以及结合具体业务场景进行分析和制定策略,能够最大程度地确保数据的一致性,保障系统的稳定运行和业务的顺利开展。同时,不断地优化和改进这些方法和机制,也是提高系统性能和可靠性的重要途径。
373 62
|
SQL 数据建模 BI
【YashanDB 知识库】用 yasldr 配置 Bulkload 模式作单线程迁移 300G 的业务数据到分布式数据库,迁移任务频繁出错
问题描述 详细版本:YashanDB Server Enterprise Edition Release 23.2.4.100 x86_64 6db1237 影响范围: 离线数据迁移场景,影响业务数据入库。 外场将部分 NewCIS 的报表业务放到分布式数据库,验证 SQL 性能水平。 操作系统环境配置: 125G 内存 32C CPU 2T 的 HDD 磁盘 问题出现的步骤/操作: 1、部署崖山分布式数据库 1mm 1cn 3dn 单线启动 yasldr 数据迁移任务,设置 32 线程的 bulk load 模式 2、观察 yasldr.log 是否出现如下错
|
缓存 安全 Java
面试中的难题:线程异步执行后如何共享数据?
本文通过一个面试故事,详细讲解了Java中线程内部开启异步操作后如何安全地共享数据。介绍了异步操作的基本概念及常见实现方式(如CompletableFuture、ExecutorService),并重点探讨了volatile关键字、CountDownLatch和CompletableFuture等工具在线程间数据共享中的应用,帮助读者理解线程安全和内存可见性问题。通过这些方法,可以有效解决多线程环境下的数据共享挑战,提升编程效率和代码健壮性。
413 6
|
缓存 安全 Java
使用 Java 内存模型解决多线程中的数据竞争问题
【10月更文挑战第11天】在 Java 多线程编程中,数据竞争是一个常见问题。通过使用 `synchronized` 关键字、`volatile` 关键字、原子类、显式锁、避免共享可变数据、合理设计数据结构、遵循线程安全原则和使用线程池等方法,可以有效解决数据竞争问题,确保程序的正确性和稳定性。
399 57
|
12月前
|
数据采集 存储 安全
Python爬虫实战:利用短效代理IP爬取京东母婴纸尿裤数据,多线程池并行处理方案详解
本文分享了一套结合青果网络短效代理IP和多线程池技术的电商数据爬取方案,针对京东母婴纸尿裤类目商品信息进行高效采集。通过动态代理IP规避访问限制,利用多线程提升抓取效率,同时确保数据采集的安全性和合法性。方案详细介绍了爬虫开发步骤、网页结构分析及代码实现,适用于大规模电商数据采集场景。

热门文章

最新文章