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/

   

目录
相关文章
|
15天前
|
前端开发 JavaScript Java
java常用数据判空、比较和类型转换
本文介绍了Java开发中常见的数据处理技巧,包括数据判空、数据比较和类型转换。详细讲解了字符串、Integer、对象、List、Map、Set及数组的判空方法,推荐使用工具类如StringUtils、Objects等。同时,讨论了基本数据类型与引用数据类型的比较方法,以及自动类型转换和强制类型转换的规则。最后,提供了数值类型与字符串互相转换的具体示例。
|
6天前
|
安全 Java API
java如何请求接口然后终止某个线程
通过本文的介绍,您应该能够理解如何在Java中请求接口并根据返回结果终止某个线程。合理使用标志位或 `interrupt`方法可以确保线程的安全终止,而处理好网络请求中的各种异常情况,可以提高程序的稳定性和可靠性。
37 6
|
19天前
|
存储 监控 小程序
Java中的线程池优化实践####
本文深入探讨了Java中线程池的工作原理,分析了常见的线程池类型及其适用场景,并通过实际案例展示了如何根据应用需求进行线程池的优化配置。文章首先介绍了线程池的基本概念和核心参数,随后详细阐述了几种常见的线程池实现(如FixedThreadPool、CachedThreadPool、ScheduledThreadPool等)的特点及使用场景。接着,通过一个电商系统订单处理的实际案例,分析了线程池参数设置不当导致的性能问题,并提出了相应的优化策略。最终,总结了线程池优化的最佳实践,旨在帮助开发者更好地利用Java线程池提升应用性能和稳定性。 ####
|
21天前
|
缓存 Java 开发者
Java多线程编程的陷阱与最佳实践####
本文深入探讨了Java多线程编程中常见的陷阱,如竞态条件、死锁和内存一致性错误,并提供了实用的避免策略。通过分析典型错误案例,本文旨在帮助开发者更好地理解和掌握多线程环境下的编程技巧,从而提升并发程序的稳定性和性能。 ####
|
15天前
|
安全 算法 Java
Java多线程编程中的陷阱与最佳实践####
本文探讨了Java多线程编程中常见的陷阱,并介绍了如何通过最佳实践来避免这些问题。我们将从基础概念入手,逐步深入到具体的代码示例,帮助开发者更好地理解和应用多线程技术。无论是初学者还是有经验的开发者,都能从中获得有价值的见解和建议。 ####
|
15天前
|
Java 调度
Java中的多线程编程与并发控制
本文深入探讨了Java编程语言中多线程编程的基础知识和并发控制机制。文章首先介绍了多线程的基本概念,包括线程的定义、生命周期以及在Java中创建和管理线程的方法。接着,详细讲解了Java提供的同步机制,如synchronized关键字、wait()和notify()方法等,以及如何通过这些机制实现线程间的协调与通信。最后,本文还讨论了一些常见的并发问题,例如死锁、竞态条件等,并提供了相应的解决策略。
40 3
|
16天前
|
监控 Java 开发者
深入理解Java中的线程池实现原理及其性能优化####
本文旨在揭示Java中线程池的核心工作机制,通过剖析其背后的设计思想与实现细节,为读者提供一份详尽的线程池性能优化指南。不同于传统的技术教程,本文将采用一种互动式探索的方式,带领大家从理论到实践,逐步揭开线程池高效管理线程资源的奥秘。无论你是Java并发编程的初学者,还是寻求性能调优技巧的资深开发者,都能在本文中找到有价值的内容。 ####
|
21天前
|
缓存 Java 开发者
Java多线程并发编程:同步机制与实践应用
本文深入探讨Java多线程中的同步机制,分析了多线程并发带来的数据不一致等问题,详细介绍了`synchronized`关键字、`ReentrantLock`显式锁及`ReentrantReadWriteLock`读写锁的应用,结合代码示例展示了如何有效解决竞态条件,提升程序性能与稳定性。
77 6
|
19天前
|
监控 Java 数据库连接
Java线程管理:守护线程与用户线程的区分与应用
在Java多线程编程中,线程可以分为守护线程(Daemon Thread)和用户线程(User Thread)。这两种线程在行为和用途上有着明显的区别,了解它们的差异对于编写高效、稳定的并发程序至关重要。
27 2
|
19天前
|
监控 Java 开发者
Java线程管理:守护线程与本地线程的深入剖析
在Java编程语言中,线程是程序执行的最小单元,它们可以并行执行以提高程序的效率和响应性。Java提供了两种特殊的线程类型:守护线程和本地线程。本文将深入探讨这两种线程的区别,并探讨它们在实际开发中的应用。
27 1
下一篇
DataWorks