Java多线程共享数据、同步、通信

简介:

一、线程共享数据

  a)继承Thread,那么我们可以创建很多个这样的类,但是每个这样的类都是相互不关联的,也就是说我们Thread类中的内容每个创建出来的类都有一份,因此它不适合作为数据共享的线程来操作。同时由于Java继承的唯一性,我们只能继承一个对象。

  b)使用runnable就可以解决唯一性和不能共享的问题(不是说使用runnable就解决了共享问题,只是相对于创建Thread来说,它可以算的上是共享了,为了获得更精确的共享问题,它必须的使用线程同步操作)。实现了runnable接口的类比较适合用作共享数据。

  一个测试例子à证明runnable能实现数据共享,thread不能

  Thread_thread一个继承了Thread的线程

  Thread_runnable是一个时间了runnable的接口,他们在run里面有共同的方法

for(int i=0;i<20;i++){
if(ticket>0){
System.out.println(ticket);
ticket--;
}
}
thread_thread th1=new thread_thread();
thread_thread th2=new thread_thread();
thread_thread th3=new thread_thread();
th1.start();
th2.start();
th3.start();

  输入了三组321321321

  因为创建的是三个对象,每一个对象都拥有自己的一个备份

  将一个runnable作为参数,实例化三个thread对象

thread_runnable ru=new thread_runnable();
Thread th1=new Thread(ru);
Thread th2=new Thread(ru);
Thread th3=new Thread(ru);
th1.start();
th2.start();
th3.start();

  输入了32133

  虽然说着不是完整意义上的数据共享,但是相当于上述打印三组完整的数据来说,它已经实现了数据共享,我们从中也可以看到,我们只创建了一个runnable对象(数据只产生了一份),它由三个Thread调用。

 新建三个runnable对象,分别给每一个thread传递

Thread th1=new Thread(new thread_runnable());
Thread th2=new Thread(new thread_runnable());
Thread th3=new Thread(new thread_runnable());
th1.start();
th2.start();
th3.start();

  打印结果是321321321

  我们可以看到我们产生了三个runnable对象,每一个都有自己的一份使用

  综上所述:只有将一个runnable对象作为参数,传递给thread对象才能实现数据共享。

  注意:当我们创建一个Thread对象,并多次调用start方法的时候,系统是不会给你创建多个Thread线程的,它只会运行那个唯一的Thread一次而已,也就是说你运行了一次start方法之后再调用一个它的start方法是没有意义的(那个Thread没有结束的情况下),系统不会给你多次运行的。

  二、线程同步

  a)线程代码块(在代码中添加Synchronized(对象){})

  i.Synchronized(对象),每个对象都有个标志位,当我们进入synchronized代码块中,系统就让这个对象的标志位变为0,就相当于给这个对象添加上了一把锁,当别的代码运行到这个代码块的时候因为加了锁,所以不能进去,当第一个程序它运行出去之后,系统就会让标志位变为1,相当于解锁。这样别的代码又可以访问了。从而实现同步(安全)操作。

  ii.当我们将我们的标志位对象放在run方法里面定义的时候,我们是不能实现同步的,因为我们每次运行一个线程,都将调用它的run方法,从而每次都会创建一个新的标志位对象,也就是说我们所有的run方法都含有自己的一个标志位对象,因此不能实现加锁的过程。一般都是放在runnable接口中进行定义的。

  b)线程方法(在代码的方法申明中public和void之间添加synchronized)

  i.每次只能有一个线程调用这个同步方法,而且每次这个方法都得运行完,这就是同步代码方法。

  ii.同步方法默认使用的是this来作为标志对象位的,这个this就是我们的当前类。

  c)注意:

  i.当一个同步代码块和一个同步代码方法使用的不是同一个对象作为标志位的时候,它们就不会实现同步,这也就是数,当两个同步代码块不使用同一个对象作为标志位,那他们就不能实现同步。

  ii.调用线程的Start方法的时候,并没有真正的运行这个代码,而只是说这个代码已经准备就绪,有运行的可能。

  三、线程通信

  a)当我们的代码中使用了synchronized(对象)同步代码块的时候,如果我们想实现线程通信,也就是如果我们想使用wait、notify或者notifyall时,我们必须在静态代码块中使用对象.wait()、对象.notify()、对象.notifyAll()来通信,不然的话讲会报Illegal的错误。

  b)Notify是唤醒同一监视器下(相当于同一个标志位对象)的第一个wait线程,而notifyall是唤醒所有的处于同一监视器下的(同一标志位对象)的线程。   



最新内容请见作者的GitHub页:http://qaseven.github.io/

   

目录
相关文章
|
16天前
|
消息中间件 监控 安全
服务Down机了,线程池中的数据如何保证不丢失?
在分布式系统与高并发应用开发中,服务的稳定性和数据的持久性是两个至关重要的考量点。当服务遭遇Down机时,如何确保线程池中处理的数据不丢失,是每一位开发者都需要深入思考的问题。以下,我将从几个关键方面分享如何在这种情况下保障数据的安全与完整性。
41 2
|
2月前
|
Java 开发者 C++
Java多线程同步大揭秘:synchronized与Lock的终极对决!
Java多线程同步大揭秘:synchronized与Lock的终极对决!
59 5
|
7天前
|
安全 Java 开发者
Java修饰符与封装:理解访问权限、行为控制与数据隐藏的重要性
Java中的修饰符和封装概念是构建健壯、易维护和扩展的Java应用程序的基石。通过合理利用访问权限修饰符和非访问修饰符,开发者能够设计出更加安全、灵活且高效的代码结构。封装不仅是面向对象编程的核心原则之一,也是提高软件项目质量和可维护性的关键策略。
10 1
|
1月前
|
消息中间件 存储 Java
服务重启了,如何保证线程池中的数据不丢失?
【8月更文挑战第30天】为确保服务重启时线程池数据不丢失,可采用数据持久化(如数据库或文件存储)、使用可靠的任务队列(如消息队列或分布式任务队列系统)、状态监测与恢复机制,以及分布式锁等方式。这些方法能有效提高系统稳定性和可靠性,需根据具体需求选择合适方案并进行测试优化。
|
8天前
|
传感器 网络协议 Java
三大硬核方式揭秘:Java如何与底层硬件和工业设备轻松通信!
大家好,我是V哥。最近与一位从事工业互联网项目的学员交流,启发我分享Java如何与底层硬件和工业设备通信。本文将介绍三种方法:1)使用`jLibModbus`库通过Modbus协议读取设备寄存器数据;2)使用JNI(Java Native Interface)直接访问硬件;3)使用`JSerialComm`库通过串口通信读取数据。每种方法都有详细步骤和示例代码,帮助你轻松实现与硬件设备的通信。无论是工业自动化还是物联网应用,这些方法都能派上用场。欢迎关注和支持!
|
1月前
|
Java API 开发者
代码小妙招:用Java轻松获取List交集数据
在Java中获取两个 `List`的交集可以通过 `retainAll`方法和Java 8引入的流操作来实现。使用 `retainAll`方法更为直接,但会修改原始 `List`的内容。而使用流则提供了不修改原始 `List`、更为灵活的处理方式。开发者可以根据具体的需求和场景,选择最适合的方法来实现。了解和掌握这些方法,能够帮助开发者在实际开发中更高效地处理集合相关的问题。
29 1
|
2月前
|
安全 Java 开发者
Java多线程同步:synchronized与Lock的“爱恨情仇”!
Java多线程同步:synchronized与Lock的“爱恨情仇”!
81 5
|
2月前
|
Java 程序员
从0到1,手把手教你玩转Java多线程同步!
从0到1,手把手教你玩转Java多线程同步!
23 3
|
2月前
|
Java 测试技术
Java多线程同步实战:从synchronized到Lock的进化之路!
Java多线程同步实战:从synchronized到Lock的进化之路!
86 1
|
2月前
|
开发者 C# 存储
WPF开发者必读:资源字典应用秘籍,轻松实现样式与模板共享,让你的WPF应用更上一层楼!
【8月更文挑战第31天】在WPF开发中,资源字典是一种强大的工具,用于共享样式、模板、图像等资源,提高了应用的可维护性和可扩展性。本文介绍了资源字典的基础知识、创建方法及最佳实践,并通过示例展示了如何在项目中有效利用资源字典,实现资源的重用和动态绑定。
44 0
下一篇
无影云桌面