实例分析多线程间共享数据 - 极悦
首页 课程 师资 教程 报名

实例分析多线程间共享数据

  • 2020-11-24 17:36:34
  • 981次 极悦

不要通过共享内存来通信,而应该通过通信来共享内存。由此可见,共享数据其实也是一门技术很深的活。而多线程编程的优势之一在于线程间共享数据的开销很小。多线程间共享数据主要有以下两种情况:

 

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

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

  }

 }

}

 

最后总结一下,Java多线程间共享数据主要关注两点就行:一是什么任务?几个任务?二是几个线程?如果只有一个任务,那说明多个线程执行一个任务,我们只要实现一个 Runnable 接口,把公共 data 放进 Runnable,把任务放进去 run() 中即可(任务注意要同步),然后开启N个线程去执行这个任务即可;如果有M个任务,那我们新建一个专门执行任务的类,把公共的 data 放进类中,把任务作为类中的同步方法即可,然后开启N个线程,每个线程中扔一个 Runnable,按照要求执行任务类中的方法即可。


选你想看

你适合学Java吗?4大专业测评方法

代码逻辑 吸收能力 技术学习能力 综合素质

先测评确定适合在学习

在线申请免费测试名额
价值1998元实验班免费学
姓名
手机
提交