动力节点旗下在线教育品牌  |  咨询热线:400-8080-105 学Java全栈,上蛙课网
首页 > 文章

多线程之共享数据

07-22 16:53 270浏览
举报 T字号
  • 大字
  • 中字
  • 小字

当一个数据被多个线程进行读取操作时,通过检查这个数据的值来进行判断并执行之后的操作是极其不安全的。因为在判断之后,这个数据的值很可能已经被其他线程修改了,判断条件也可能已经不成立了,但此时已经过了判断,之后的操作也就“将错就错”地继续进行这个时候就需要用到多线程共享数据

多线程的共享数据是多线程众多机制中的对数据处理的一种不可或缺的功能,可以有效地防止数据在多线程的数据错乱问题。 Java 的传统线程机制中共享数据的方式可以大致分为二种。

  • 多个线程行为一致,共同操作一个数据源: 也就是每个线程执行的代码相同,可以使用同一个 Runnable 对象,这个 Runnable 对象中有那个共享数据,例如,最经典的有说服力的卖票系统。

如果多个线程执行的代码相同的话就可以使用同一个Runnable,Runable中包含了共享的数据对象:

public class ThreadTest1 {

public static void main(String[] args) {

ShareData shareData = new ShareData();//共享的数据对象

for (int i = 0; i < 4; i++) {

new Thread(new RunnableCusToInc(shareData), "Thread " + i).start();

}

}

}

 

/**

 * 共享数据类

 **/

class ShareData {

private int num = 10;

 

public synchronized void inc() {

num++;

System.out.println(Thread.currentThread().getName()

+ ": invoke inc method num =" + num);

try {

Thread.sleep(1000);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

 

/**

 *多线程类

 **/

class RunnableCusToInc implements Runnable {

private ShareData shareData;//共享的数据对象

 

public RunnableCusToInc(ShareData data) {

this.shareData = data;

}

 

public void run() {

for (int i = 0; i < 5; i++) {

shareData.inc();

}

}

}

  • 多个线程行为不一致,共同操作一个数据源:也就是每个线程执行的代码不同,这时候需要用不同的Runnable 对象。例如,银行存取款。

不同线程操作同一共享对象,不同线程执行的代码也不相同.

        (1).将共享数据封装在另外一个对象中,然后将这个对象逐一传递给各个 Runnable 对象。每个线程对共享

数据的操作方法也分配到那个对象身上去完成,这样容易实现针对该数据进行的各个操作的互斥和通信

package test.demo;

 

public class ThreadTest2 {

public static void main(String[] args) {

ShareData2 shareData = new ShareData2();

for (int i = 0; i < 4; i++) {

if (i % 2 == 0) {

new Thread(new RunnableCusToInc2(shareData), "Thread " + i)

.start();

} else {

new Thread(new RunnableCusToInc3(shareData), "Thread " + i)

.start();

}

}

}

}

 

/**

 * 共享数据类

 **/

class ShareData2 {

private int num = 10;

 

public synchronized void inc() {

num++;

System.out.println(Thread.currentThread().getName()

+ ": invoke inc method num =" + num);

try {

Thread.sleep(1000);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

 

/**

 * 多线程类

 **/

class RunnableCusToInc2 implements Runnable {

private ShareData2 shareData;

 

public RunnableCusToInc2(ShareData2 data) {

this.shareData = data;

}

 

public void run() {

for (int i = 0; i < 5; i++) {

shareData.inc();

}

}

}

 

class RunnableCusToInc3 implements Runnable {

private ShareData2 shareData;

 

public RunnableCusToInc3(ShareData2 data) {

this.shareData = data;

}

 

public void run() {

for (int i = 0; i < 5; i++) {

shareData.inc();

System.out.println("33333333333333333333333");

}

}

}

(2).将这些 Runnable 对象作为某一个类中的内部类,共享数据作为这个外部类中的成员变量,每个线程对共享数据的操作方法也分配给外部类,以便实现对共享数据进行的各个操作的互斥和通信,作为内部类的各个Runnable 对象调用外部类的这些方法。

public class ThreadTest3 {

public static void main(String[] args) {

// 公共数据

final ShareData shareData = new ShareData();

for (int i = 0; i < 4; i++) {

if (i % 2 == 0) {

new Thread(new Runnable() {

@Override

public void run() {

for (int i = 0; i < 5; i++) {

shareData.inc();

}

}

}, "Thread " + i).start();

} else {

new Thread(new Runnable() {

@Override

public void run() {

for (int i = 0; i < 5; i++) {

shareData.dec();

}

}

}, "Thread " + i).start();

}

}

}

 

class ShareData {

private int num = 10;

 

public synchronized void inc() {

num++;

System.out.println(Thread.currentThread().getName()

+ ": invoke inc method num =" + num);

try {

Thread.sleep(1000);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

 

public synchronized void dec() {

num--;

System.err.println(Thread.currentThread().getName()

+ ": invoke dec method num =" + num);

try {

Thread.sleep(1000);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

}

通过上面的几个实例,我们不难发现其实多线程共享数据最主要的还是互斥,多个线程共享一个变量,针对变量的操作实现原子性即可。想要学习java多线程的更多知识,欢迎观看本站的多线程专业视频课程,助力你的java学习之路平步青云!

0人推荐
共同学习,写下你的评论
0条评论
代码小兵1271
程序员代码小兵1271

11篇文章贡献55922字

作者相关文章更多>

推荐相关文章更多>

Java数据结构

HelloWorld10-31 08:24

浅谈MySQL中SQL优化的常用方法

军哥08-12 23:29

五分钟读懂UML类图

江湖人称小李白12-10 10:41

MyBatis开发框架的四大核心

IT逐梦者08-17 21:43

一次搞定continue,break和return

HelloWorld11-06 11:19

发评论

举报

0/150

取消