热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Java多线程知识简单梳理

1.多线程的创建继承Thread类实现Runnable接口匿名类2.常见线程方法暂停当前线程:Thread.sleep(1000)加入主线程:t1.join(),主线程会等待该线程

1.多线程的创建



  • 继承Thread类

  • 实现Runnable接口

  • 匿名类

2.常见线程方法



  • 暂停当前线程:Thread.sleep(1000)

  • 加入主线程:t1.join(),主线程会等待该线程结束才会继续往下运行

  • 设置线程优先级:t1.setPriority(Thread.MAX_PRIORITY)、t1.setPriority(Thread.MIN_PRIORITY)

  • 临时暂停:Thread.yield()

  • 设置守护线程:t1.setDaemon(true)

3.同步



  • 同步问题的产生原因:多个线程同时在操作一个对象

  • 同步问题的解决思路:有线程在操作对象时其他线程无法访问该对象

  • Synchronized同步对象概念

    a.synchronized表示当前线程独占了同步对象,如果其他线程试图占有对象,就会等待;直到当前线程释放对同步对象的占用

    b.多线程的操作需要建立在占有同步对象的基础上,而同步对象在同一时间也只能被一个线程占有;间接地同一时间,同步对象只能被一个线程修改。

    c.释放同步对象的方式:synchronized块自然结束或有异常抛出



  • Synchronized解决同步问题:任意对象都可以成为同步对象,包括实例对象、this、类方法

  • 线程安全的类

    a.如果一个类,其方法都是有synchronized修饰的,那么该类就该叫做线程安全的类;同一时间只有一个线程能够进入这种类的一个实例去修改数据,进而保证了这个实例中数据的安全(不会同时被多线程而变成脏数据)

    b.常见线程安全相关的面试题

      1.HashMap和Hashtable的区别一:HashMap可以存放null,Hashtable不能存放null;

      2.StringBuffer和StringBuilder的区别一:StringBuffer是线程安全的,StringBuilder是非线程安全的;区别二:当进行大量字符串拼接操作的时候,如果是单线程就用StringBuilder会更快些;如果是多线程,就需要使用StringBuffer保证数据的安全性

      3.ArrayList和Vector的区别:类声明一致,区别在于Vector是线程安全的类,而ArrayList是非线程安全的。

      4.把非线程安全的集合转换为线程安全:ArrayList是非线程安全的,多个线程可以同时进入一个ArrayList对象的add方法;借助Collections.synchronizedList,可以把ArrayList转换为线程安全的List。与此类似的还有HashSet,LinkedList,HashMap等非线程安全的类,都可以通过工具类Collections转换为线程安全的。

4.死锁



  •  当业务比较复杂,多线程应用里有可能会发生死锁a.线程1首先占有对象1,接着试图占有对象2;b.线程2首先占有对象2,接着试图占有对象1;c.线程1会等待线程2释放对象2;d.线程2会等待线程1释放对象1;e.两个线程就会一直等待下去。。。                                                                        



5.交互



  • 线程之间有交互通知的需求

    a.不好的解决方式:线程中使用while等循环语句去处理判断语句,会大量占用CPU,拖慢性能;

    b.使用wait和notify进行线程交互

    (1)this.wait()表示让占有this的线程等待,并临时释放占有;

    (2)this.notify()表示唤醒那等待在this的线程;

    c.关于wait、notify、notifyAll

    (1)wait方法和notify方法并不是Thread线程上的方法,它们是Object上的方法;因为所有的Object都可以用来作为同步对象,所以准确的来说,wait和notify是同步对象上的方法。

    (2)wait()的意思是:让占用了这个同步对象的线程,临时释放当前的占用并且等待;所以调用wait是有前提条件的,一定是在sycnhronized块里,否则就会出错。

    (3)notify()的意思是:通知一个等待在这个同步对象上的线程,你可以苏醒过来了,有机会重新占用当前对象了。

    (4)notifyAll()的意思是:通知所有的等待在这个同步对象上的线程,你们可以苏醒过来了,有机会重新占用当前对象了。

    d.线程交互:【练习题】假设加血线程运行得更加频繁,Hero类属性hp最大值是1000;设计加血线程和减血线程的交互,让回血回满之后,加血线程等待,直到有减血线程减血。

       Hero类回血、减血方法实现:

               

    线程实例化

               

    e.多线程交互:【练习题】在前面练习的基础上,增加回血线程到2条,减血线程到5条,同时运行;运行一段时间后,观察会发生的错误,分析错误原因并考虑解决办法。

       错误:在目前的状态下,会导致hp变为负数;这是因为减血线程调用hurt()方法结束后,调用notify有可能唤醒另一个减血线程,这就导致hp会不停的减下去。

       

       解决办法:减血线程被唤醒后,要再次查看当前hp;如果当前hp<=1,那么就继续等待。把if改为while,当线程被唤醒后会重复查看hp的值,只有hp大于1才会继续往下执行。

       

    f.生产者消费者问题:生产者消费者问题是一个非常典型性的线程交互的问题。

    (1)使用栈来存放数据

      (1.1)把栈改造为支持线程安全

      (1.2)把栈的边界操作进行处理,当栈里的数据是0的时候,访问pull的线程就会等待。当栈里的数据是200的时候,访问push的线程就会等待。

    (2)提供一个生产者(Producer)线程类,生产随机大写字符压入到堆栈

    (3)提供一个消费者(Consumer)线程类,从堆栈中弹出字符并打印到控制台

    (4)提供一个测试类,使两个生产者和三个消费者线程同时运行,结果类似如下:

        通过LinkList实现Stack

      

        ProducerThread线程类实现

      

        ConsumerThread线程类实现

      

       测试类

      

6.线程池



  • 每一个线程的启动和结束都是比较消耗时间和占用资源的,如果在系统中用到了很多的线程,大量的启动和结束动作会导致系统的性能变卡,响应变慢;为了解决这个问题,引入线程池这种设计思想。线程池的模式很像生产者消费者模式

7.Lock对象

8.原子访问

 



推荐阅读
  • 在 Java 中,`join()` 方法用于使当前线程暂停,直到指定的线程执行完毕后再继续执行。此外,`join(long millis)` 方法允许当前线程在指定的毫秒数后继续执行。 ... [详细]
  • Python 数据可视化实战指南
    本文详细介绍如何使用 Python 进行数据可视化,涵盖从环境搭建到具体实例的全过程。 ... [详细]
  • 本文是Java并发编程系列的开篇之作,将详细解析Java 1.5及以上版本中提供的并发工具。文章假设读者已经具备同步和易失性关键字的基本知识,重点介绍信号量机制的内部工作原理及其在实际开发中的应用。 ... [详细]
  • 阿里巴巴终面技术挑战:如何利用 UDP 实现 TCP 功能?
    在阿里巴巴的技术面试中,技术总监曾提出一道关于如何利用 UDP 实现 TCP 功能的问题。当时回答得不够理想,因此事后进行了详细总结。通过与总监的进一步交流,了解到这是一道常见的阿里面试题。面试官的主要目的是考察应聘者对 UDP 和 TCP 在原理上的差异的理解,以及如何通过 UDP 实现类似 TCP 的可靠传输机制。 ... [详细]
  • Python多线程编程技巧与实战应用详解 ... [详细]
  • 深入剖析Java中SimpleDateFormat在多线程环境下的潜在风险与解决方案
    深入剖析Java中SimpleDateFormat在多线程环境下的潜在风险与解决方案 ... [详细]
  • Java并发机制详解及其在数据安全性保障中的应用方案 ... [详细]
  • 本文详细介绍了在 Oracle 数据库中使用 MyBatis 实现增删改查操作的方法。针对查询操作,文章解释了如何通过创建字段映射来处理数据库字段风格与 Java 对象之间的差异,确保查询结果能够正确映射到持久层对象。此外,还探讨了插入、更新和删除操作的具体实现及其最佳实践,帮助开发者高效地管理和操作 Oracle 数据库中的数据。 ... [详细]
  • 本文将继续探讨 JavaScript 函数式编程的高级技巧及其实际应用。通过一个具体的寻路算法示例,我们将深入分析如何利用函数式编程的思想解决复杂问题。示例中,节点之间的连线代表路径,连线上的数字表示两点间的距离。我们将详细讲解如何通过递归和高阶函数等技术实现高效的寻路算法。 ... [详细]
  • 本文深入探讨了Java多线程环境下的同步机制及其应用,重点介绍了`synchronized`关键字的使用方法和原理。`synchronized`关键字主要用于确保多个线程在访问共享资源时的互斥性和原子性。通过具体示例,如在一个类中使用`synchronized`修饰方法,展示了如何实现线程安全的代码块。此外,文章还讨论了`ReentrantLock`等其他同步工具的优缺点,并提供了实际应用场景中的最佳实践。 ... [详细]
  • 在 Linux 环境下,多线程编程是实现高效并发处理的重要技术。本文通过具体的实战案例,详细分析了多线程编程的关键技术和常见问题。文章首先介绍了多线程的基本概念和创建方法,然后通过实例代码展示了如何使用 pthreads 库进行线程同步和通信。此外,还探讨了多线程程序中的性能优化技巧和调试方法,为开发者提供了宝贵的实践经验。 ... [详细]
  • Python全局解释器锁(GIL)机制详解
    在Python中,线程是操作系统级别的原生线程。为了确保多线程环境下的内存安全,Python虚拟机引入了全局解释器锁(Global Interpreter Lock,简称GIL)。GIL是一种互斥锁,用于保护对解释器状态的访问,防止多个线程同时执行字节码。尽管GIL有助于简化内存管理,但它也限制了多核处理器上多线程程序的并行性能。本文将深入探讨GIL的工作原理及其对Python多线程编程的影响。 ... [详细]
  • 深入浅析JVM垃圾回收机制与收集器概述
    本文基于《深入理解Java虚拟机:JVM高级特性与最佳实践(第3版)》的阅读心得进行整理,详细探讨了JVM的垃圾回收机制及其各类收集器的特点与应用场景。通过分析不同垃圾收集器的工作原理和性能表现,帮助读者深入了解JVM内存管理的核心技术,为优化Java应用程序提供实用指导。 ... [详细]
  • 如何利用Java 5 Executor框架高效构建和管理线程池
    Java 5 引入了 Executor 框架,为开发人员提供了一种高效管理和构建线程池的方法。该框架通过将任务提交与任务执行分离,简化了多线程编程的复杂性。利用 Executor 框架,开发人员可以更灵活地控制线程的创建、分配和管理,从而提高服务器端应用的性能和响应能力。此外,该框架还提供了多种线程池实现,如固定线程池、缓存线程池和单线程池,以适应不同的应用场景和需求。 ... [详细]
  • 本文深入解析了Java 8并发编程中的`AtomicInteger`类,详细探讨了其源码实现和应用场景。`AtomicInteger`通过硬件级别的原子操作,确保了整型变量在多线程环境下的安全性和高效性,避免了传统加锁方式带来的性能开销。文章不仅剖析了`AtomicInteger`的内部机制,还结合实际案例展示了其在并发编程中的优势和使用技巧。 ... [详细]
author-avatar
丫头2502892725
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有