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

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

  1. public class MultiThreadShareData
  2. {
  3. public static void main(String[] args)
  4. {
  5. SaleTickets sale = new SaleTickets();
  6. new Thread(sale).start();
  7. new Thread(sale).start();
  8. }
  9. }
  10. class SaleTickets implements Runnable
  11. {
  12. public int allTicketCount = 20;
  13. public void run()
  14. {
  15. while (allTicketCount > 0)
  16. {
  17. sale();
  18. }
  19. }
  20. public synchronized void sale()
  21. {
  22. System.out.println("剩下" + allTicketCount);
  23. allTicketCount--;
  24. }
  25. }

 SaleTickets这个对象中就有需要共享的数据allTicketCount,两个线程使用同一个SaleTickets,就可以共享allTicketCount了。

二、每个线程执行的代码不相同:

方法:将需要共享的数据封装成一个对象,将该对象传给执行不同代码的Runnable对象。
方法:将这些执行不同代码的Runnable对象作为内部类。

看例子:有4个线程,其中有2个线程对每次对j +1,有2个线程对每次对j -1。加减操作无顺序。

(1)方法1:

  1. public class MultiThreadShareData3
  2. {
  3. public static void main(String[] args)
  4. {
  5. int j = 10;
  6. NumberInfo nInfo = new NumberInfo(j);
  7. for (int i = 0; i < 2; i++)
  8. {
  9. new Thread(new NumberInfoAdd("增线程", nInfo)).start();
  10. new Thread(new NumberInfoMinus("减线程", nInfo)).start();
  11. }
  12. }
  13. }
  14. class NumberInfo
  15. {
  16. private int number;
  17. public NumberInfo(int number)
  18. {
  19. this.number = number;
  20. }
  21. public int getNumber()
  22. {
  23. return number;
  24. }
  25. public void setNumber(int number)
  26. {
  27. this.number = number;
  28. }
  29. public void add()
  30. {
  31. System.out.println("数值:" + (++number));
  32. }
  33. public void minus()
  34. {
  35. System.out.println("数值:" + (--number));
  36. }
  37. }
  38. // 增操作
  39. class NumberInfoAdd implements Runnable
  40. {
  41. private String name;
  42. private NumberInfo nInfo;
  43. public NumberInfoAdd(String name, NumberInfo nInfo)
  44. {
  45. this.name = name;
  46. this.nInfo = nInfo;
  47. }
  48. public void run()
  49. {
  50. add();
  51. }
  52. public void add()
  53. {
  54. synchronized (nInfo)
  55. {
  56. System.out.print(name + "--");
  57. nInfo.add();
  58. }
  59. }
  60. }
  61. // 减操作
  62. class NumberInfoMinus implements Runnable
  63. {
  64. private String name;
  65. private NumberInfo nInfo;
  66. public NumberInfoMinus(String name, NumberInfo nInfo)
  67. {
  68. this.name = name;
  69. this.nInfo = nInfo;
  70. }
  71. public void run()
  72. {
  73. minus();
  74. }
  75. public void minus()
  76. {
  77. synchronized (nInfo)
  78. {
  79.    System.out.print(name + "--");
  80.    nInfo.minus();
  81.    }
  82. }
  83. }

(2)方法2:

  1. public class MultiThreadShareData4
  2. {
  3. int j = 10;
  4. public static void main(String[] args)
  5. {
  6. MultiThreadShareData4 m = new MultiThreadShareData4();
  7. for (int i = 0; i < 2; i++)
  8. {
  9. new Thread(m.new NumberInfoAdd()).start();
  10. new Thread(m.new NumberInfoMinus()).start();
  11. }
  12. }
  13. public synchronized void add()
  14. {
  15. System.out.println("增加后数值:" + (++j));
  16. }
  17. public synchronized void minus()
  18. {
  19. System.out.println("減少后数值:" + (--j));
  20. }
  21. // 增
  22. class NumberInfoAdd implements Runnable
  23. {
  24. public void run()
  25. {
  26. add();
  27. }
  28. }
  29. // 减
  30. class NumberInfoMinus implements Runnable
  31. {
  32. public void run()
  33. {
  34. minus();
  35. }
  36. }
  37. }

执行结果可能是

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

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

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

  1. public class MultiThreadShareData2
  2. {
  3. public static void main(String[] args)
  4. {
  5. TicketInfo tInfo = new TicketInfo(20);
  6. new Thread(new SaleTickets2("线程1", tInfo)).start();
  7. new Thread(new SaleTickets2("线程2", tInfo)).start();
  8. }
  9. }
  10. class TicketInfo
  11. {
  12. private int allTicketCount;
  13. public TicketInfo(int allTicketCount)
  14. {
  15. this.allTicketCount = allTicketCount;
  16. }
  17. public int getAllTicketCount()
  18. {
  19. return allTicketCount;
  20. }
  21. public void setAllTicketCount(int allTicketCount)
  22. {
  23. this.allTicketCount = allTicketCount;
  24. }
  25. public void sale()
  26. {
  27. System.out.println("剩余:" + allTicketCount--);
  28. }
  29. }
  30. class SaleTickets2 implements Runnable
  31. {
  32. private String name;
  33. private TicketInfo tInfo;
  34. public SaleTickets2(String name, TicketInfo tInfo)
  35. {
  36. this.name = name;
  37. this.tInfo = tInfo;
  38. }
  39. public void run()
  40. {
  41. while (tInfo.getAllTicketCount() > 0)
  42. {
  43. sale();
  44. }
  45. }
  46. public void sale()
  47. {
  48. synchronized (tInfo)
  49. {
  50. System.out.print(name + "--");
  51. tInfo.sale();
  52. }
  53. }
  54. }

Java基础知识强化102:线程间共享数据的更多相关文章

  1. Java并发基础09. 多个线程间共享数据问题

    先看一个多线程间共享数据的问题: 设计四个线程,其中两个线程每次对data增加1,另外两个线程每次对data减少1. 从问题来看,很明显涉及到了线程间通数据的共享,四个线程共享一个 data,共同操作 ...

  2. Java基础知识强化之集合框架笔记76:ConcurrentHashMap之 ConcurrentHashMap简介

    1. ConcurrentHashMap简介: ConcurrentHashMap是一个线程安全的Hash Table,它的主要功能是提供了一组和Hashtable功能相同但是线程安全的方法.Conc ...

  3. 详解 Qt 线程间共享数据(用信号槽方式)

    使用共享内存.即使用一个两个线程都能够共享的变量(如全局变量),这样两个线程都能够访问和修改该变量,从而达到共享数据的目的. Qt 线程间共享数据是本文介绍的内容,多的不说,先来啃内容.Qt线程间共享 ...

  4. Disruptor 线程间共享数据无需竞争

    队列的作用是缓冲 缓冲到 队列的空间里.. 线程间共享数据无需竞争 原文 地址  作者  Trisha   译者:李同杰 LMAX Disruptor 是一个开源的并发框架,并获得2011 Duke’ ...

  5. 详解 Qt 线程间共享数据(使用signal/slot传递数据,线程间传递信号会立刻返回,但也可通过connect改变)

    使用共享内存.即使用一个两个线程都能够共享的变量(如全局变量),这样两个线程都能够访问和修改该变量,从而达到共享数据的目的. Qt 线程间共享数据是本文介绍的内容,多的不说,先来啃内容.Qt线程间共享 ...

  6. Qt学习:线程间共享数据(使用信号槽传递数据,必须提前使用qRegisterMetaType来注册参数的类型)

    Qt线程间共享数据主要有两种方式: 使用共享内存.即使用一个两个线程都能够共享的变量(如全局变量),这样两个线程都能够访问和修改该变量,从而达到共享数据的目的: 使用singal/slot机制,把数据 ...

  7. Java基础知识强化100:JVM 内存模型

    一. JVM内存模型总体架构图:  方法区和堆由所有线程共享,其他区域都是线程私有的 二. JVM内存模型的结构分析: 1. 类装载器(classLoader) 类装载器,它是在java虚拟机中用途是 ...

  8. JAVA 并发编程-多个线程之间共享数据

    原文地址:http://blog.csdn.net/hejingyuan6/article/details/47053409# 多线程共享数据的方式: 1,如果每个线程执行的代码相同,可以使用同一个R ...

  9. JAVA 并发编程-多个线程之间共享数据(六)

    多线程共享数据的方式: 1.假设每一个线程运行的代码同样.能够使用同一个Runnable对象,这个Runnable对象中有那个共享数据,比如,卖票系统就能够这么做. 2,假设每一个线程运行的代码不同. ...

随机推荐

  1. 多校6 1010 HDU5802 Windows 10 dfs

    // 多校6 1010 HDU5802 Windows 10 // 题意:从p到q有三种操作,要么往上升只能1步,要么往下降,如果连续往下降就是2^n, // 中途停顿或者向上,下次再降的时候从1开始 ...

  2. Lucene学习笔记: 五,Lucene搜索过程解析

    一.Lucene搜索过程总论 搜索的过程总的来说就是将词典及倒排表信息从索引中读出来,根据用户输入的查询语句合并倒排表,得到结果文档集并对文档进行打分的过程. 其可用如下图示: 总共包括以下几个过程: ...

  3. HDU-4720 Naive and Silly Muggles 圆的外心

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4720 先两两点之间枚举,如果不能找的最小的圆,那么求外心即可.. //STATUS:C++_AC_0M ...

  4. TreeMap实现原理

    摘要 研究项目底层代码时,发现项目中的数据的缓存用的是TreeMap来实现对数据的缓存管理.本片博文就TreeMap的源码.原理以及用法做一个探究 在用TreeMap之前我们要对TreeMap有个整体 ...

  5. Spark生态之Spark Graphx

  6. 修改Oracle 10g Express Edition默认的8080端口

    http://sucre.blog.51cto.com/1084905/475531 ————————————————————————————————————————————————————————— ...

  7. Android实例-Delphi开发蓝牙官方实例解析(XE10+小米2+小米5)

    相关资料:1.http://blog.csdn.net/laorenshen/article/details/411498032.http://www.cnblogs.com/findumars/p/ ...

  8. UVALive 7325 Book Borders (模拟)

    Book Borders 题目链接: http://acm.hust.edu.cn/vjudge/contest/127407#problem/B Description A book is bein ...

  9. 从 ALAsset 中取出属性

    #pragma mark - 从相册数组中取出所有的 图片数据 -(NSMutableArray *)getImageFromAlbumArray:(NSArray *)albumArr { NSMu ...

  10. 通过 监听器获取sessionId

    package shopping; import java.util.HashMap; import java.util.Map; import javax.servlet.http.HttpSess ...