线程间共享数据

简介:

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

若每个线程执行的代码相同,共享数据就比较方便。可以使用同一个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

相关文章
|
27天前
|
消息中间件 监控 安全
服务Down机了,线程池中的数据如何保证不丢失?
在分布式系统与高并发应用开发中,服务的稳定性和数据的持久性是两个至关重要的考量点。当服务遭遇Down机时,如何确保线程池中处理的数据不丢失,是每一位开发者都需要深入思考的问题。以下,我将从几个关键方面分享如何在这种情况下保障数据的安全与完整性。
43 2
|
5月前
|
消息中间件 Java Kafka
实时计算 Flink版操作报错之Apache Flink中的SplitFetcher线程在读取数据时遇到了未预期的情况,该怎么解决
在使用实时计算Flink版过程中,可能会遇到各种错误,了解这些错误的原因及解决方法对于高效排错至关重要。针对具体问题,查看Flink的日志是关键,它们通常会提供更详细的错误信息和堆栈跟踪,有助于定位问题。此外,Flink社区文档和官方论坛也是寻求帮助的好去处。以下是一些常见的操作报错及其可能的原因与解决策略。
|
1月前
|
消息中间件 存储 Java
服务重启了,如何保证线程池中的数据不丢失?
【8月更文挑战第30天】为确保服务重启时线程池数据不丢失,可采用数据持久化(如数据库或文件存储)、使用可靠的任务队列(如消息队列或分布式任务队列系统)、状态监测与恢复机制,以及分布式锁等方式。这些方法能有效提高系统稳定性和可靠性,需根据具体需求选择合适方案并进行测试优化。
110 5
|
2月前
处理串口线程数据的函数
【8月更文挑战第4天】处理串口线程数据的函数。
24 4
|
2月前
|
数据处理 Python
解锁Python多线程编程魔法,告别漫长等待!让数据下载如飞,感受科技带来的速度与激情!
【8月更文挑战第22天】Python以简洁的语法和强大的库支持在多个领域大放异彩。尽管存在全局解释器锁(GIL),Python仍提供多线程支持,尤其适用于I/O密集型任务。通过一个多线程下载数据的例子,展示了如何使用`threading`模块创建多线程程序,并与单线程版本进行了性能对比。实验表明,多线程能显著减少总等待时间,但在CPU密集型任务上GIL可能会限制其性能提升。此案例帮助理解Python多线程的优势及其适用场景。
29 0
|
2月前
|
缓存 Java 容器
多线程环境中的虚假共享是什么?
【8月更文挑战第21天】
27 0
|
2月前
|
NoSQL Redis
Lettuce的特性和内部实现问题之在同步调用模式下,业务线程是如何拿到结果数据的
Lettuce的特性和内部实现问题之在同步调用模式下,业务线程是如何拿到结果数据的
|
3月前
|
Rust 安全 程序员
Rust与C++的区别及使用问题之Rust解决多线程下的共享的问题如何解决
Rust与C++的区别及使用问题之Rust解决多线程下的共享的问题如何解决
|
4月前
|
存储 测试技术
【工作实践(多线程)】十个线程任务生成720w测试数据对系统进行性能测试
【工作实践(多线程)】十个线程任务生成720w测试数据对系统进行性能测试
47 0
【工作实践(多线程)】十个线程任务生成720w测试数据对系统进行性能测试
|
3月前
|
存储 缓存 NoSQL
架构设计篇问题之在数据割接过程中,多线程处理会导致数据错乱和重复问题如何解决
架构设计篇问题之在数据割接过程中,多线程处理会导致数据错乱和重复问题如何解决