java中线程挂起的几种方式详解

前言

在Java中使用线程的时候肯定会有线程挂起的这种情况出现,在Java中提供了3种方式:suspend/resume、wait/notify,notifyAll、park/unpark。

1.suspend/resume

这种方式已经在Java中被弃用,因为它容易引起死锁。在使用关键字synchronized的时候如

synchronized (this) {
 Thread.currentThread().suspend();
} 

这个时候使用resume方法是无法唤醒线程的,还有一种情况是如果在resume方法之后才进行suspend方法的调用,这个也是无法进行suspend方法的唤醒的,因为这个事件发生的顺序已经造成了死锁的出现。

2.wait/notify,notifyAll

这个是Java中常用的线程挂起方法,当调用wait方法的时候线程会自动的释放掉占有的线程资源锁,然后通过notify或notifyAll方法进行wait方法的唤醒,因此在这个地方不会出现死锁,当时如suspend/resume中提到的,如果在notify或notifyAll方法之后在进行wait操作,那么肯定也是会出现死锁的。

这里必须说明一下的是sleep方法,虽然它也能将线程挂起,但是它会产生InterruptedException异常,当sleep一定时间后它将会自动执行后面的方法,也可以通过interrupt方法进行主动打断sleep方法进行线程唤醒。

3.park/unpark

park的字面量意思是指停车场的意思,使用park来挂起线程后需要调用unpark来进行唤醒,这个没有先后顺序的区分,如果你提前进行了unpark,然后在进行park也是可以的,但是提前了的多个unpark只能看做是一个unpark,不能进行重复叠加,如果再次park的话需要新的unpark来进行唤醒操作,这个比如你在停车场进行停车操作,你如果提前进行了预约停车,你在未进入停车场之前都是可以进行多次预约的,这所有的预约只扣一次钱(unpark),但是这所有的预约操作都看作是你这一次进入停车场停车(park)的凭证,如果你离开了通过缴费凭证(unpark)一旦你想进行下一次停车,那么已经使用过的预约都不能进行作数了,你只能再次预约或者直接进入停车场,一旦要离开只能再次缴费(unpark)。

调用park/unpark使用的是LockSupport.park()/LockSupport.unpark()。

使用park/unpark的使用使用synchronized关键字也会出现死锁的情况,因为它并不释放线程所占用的锁资源,所以使用的时候也需要注意。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Java 并发编程之线程挂起、恢复与终止

    挂起和恢复线程 Thread 的API中包含两个被淘汰的方法,它们用于临时挂起和重启某个线程,这些方法已经被淘汰,因为它们是不安全的,不稳定的.如果在不合适的时候挂起线程(比如,锁定共享资源时),此时便可能会发生死锁条件--其他线程在等待该线程释放锁,但该线程却被挂起了,便会发生死锁.另外,在长时间计算期间挂起线程也可能导致问题. 下面的代码演示了通过休眠来延缓运行,模拟长时间运行的情况,使线程更可能在不适当的时候被挂起: public class DeprecatedSuspendResume

  • 详解Java编程中线程的挂起、恢复和终止的方法

    有时,线程的挂起是很有用的.例如,一个独立的线程可以用来显示当日的时间.如果用户不希望用时钟,线程被挂起.在任何情形下,挂起线程是很简单的,一旦挂起,重新启动线程也是一件简单的事. 挂起,终止和恢复线程机制在Java 2和早期版本中有所不同.尽管你运用Java 2的途径编写代码,你仍需了解这些操作在早期Java环境下是如何完成的.例如,你也许需要更新或维护老的代码.你也需要了解为什么Java 2会有这样的变化.因为这些原因,下面内容描述了执行线程控制的原始方法,接着是Java 2的方法. Jav

  • java线程池实现批量下载文件

    本文实例为大家分享了java线程池实现批量下载文件的具体代码,供大家参考,具体内容如下 1 创建线程池 package com.cheng.webb.thread; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.ExecutorService; import java.util.concurrent.ThreadFactory; import java.util.concurrent.Thr

  • Java实现的两个线程同时运行案例

    本文实例讲述了Java实现的两个线程同时运行.分享给大家供大家参考,具体如下: /** * 两个案例同时运行案例 * 1:这个两个线程并不是有规律的运行而是有没有规律的交替运行 */ package com.test3; public class Demo10_3 { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub Pig pig=new Pig(10

  • Java多线程之火车售票系统

    Java多线程之火车售票(Thread和Runnable的区别) java中实现多线程的方式有两种 继承Thread类 实现Runnable接口 继承了Thread类的类,使用对象.start()启动线程 实现了Runnable类的类,使用new Thread(new Runnable的实现类()).start()启动 下面有个经典例子,很适合用实现Runnable接口的类去实现. 火车售票问题简单分析: 1.票数是共用的,不能将一张票买多次.  2.同时有多个售票点在出售车票,即有多个线程存在

  • java多线程实现文件下载

    本文实例为大家分享了java多线程实现文件下载的具体代码,供大家参考,具体内容如下 1.DownloadManager类 import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.Ht

  • Java多线程批量数据导入的方法详解

    前言: 当遇到大量数据导入时,为了提高处理的速度,可以选择使用多线程来批量处理这些处理.常见的场景有: 大文件导入数据库(这个文件不一定是标准的CSV可导入文件或者需要在内存中经过一定的处理) 数据同步(从第三方接口拉取数据处理后写入自己的数据库) 以上的场景有一个共性,这类数据导入的场景简单来说就是将数据从一个数据源移动到另外一个数据源,而其中必定可以分为两步 数据读取:从数据源读取数据到内存 数据写入:将内存中的数据写入到另外一个数据源,可能存在数据处理 而且根据读取的速度一般会比数据写入的

  • java中线程挂起的几种方式详解

    前言 在Java中使用线程的时候肯定会有线程挂起的这种情况出现,在Java中提供了3种方式:suspend/resume.wait/notify,notifyAll.park/unpark. 1.suspend/resume 这种方式已经在Java中被弃用,因为它容易引起死锁.在使用关键字synchronized的时候如 synchronized (this) { Thread.currentThread().suspend(); } 这个时候使用resume方法是无法唤醒线程的,还有一种情况是

  • java中创建写入文件的6种方式详解与源码实例

    在java中有很多的方法可以创建文件写文件,你是否真的认真的总结过?下面笔者就帮大家总结一下java中创建文件的五种方法. Files.newBufferedWriter(Java 8) Files.write(Java 7 推荐) PrintWriter File.createNewFile FileOutputStream.write(byte[] b) 管道流 实际上不只这5种,通过管道流的排列组合,其实有更多种,但是笔者总结的这五种可以说是最常用及最佳实践,前提小知识 以前我在写技术文章

  • Java SpringBoot启动指定profile的8种方式详解

    目录 配置文件中设置 命令行设置 IDEA中设置 1.program arguments程序参数 2.VM options虚拟机参数 3.Active profiles 参数 遇到的问题 总结 配置文件中设置 通常在公司级别的项目中,我们可能会写多个application- dev/prod.yml ,然后我们通常会在application.yml配置文件中写入 spring: profiles: active: dev 这里会指定激活的profile是application- dev.yml

  • Android中Intent传递对象的3种方式详解

    前言 相信Intent的用法大家已经比较熟悉了,Intent可以用来启动Activity,Service等等,同时我们也可以通过Intent来进行传递数据,当我们使用Intent在Activity 间传递信息时发现putExtra() 方法并不支持自定义对象的传输,下面就来介绍三种解决方式. 一.Serializable 方式 这是最简单的一种方法,因为我们要做的就是让我们自定义的对象实现 Serializable 这个空接口. public class Person implements Se

  • C#中增强类功能的几种方式详解

    前言 本文主要讲解如何利用C#语言自身的特性来对一个类的功能进行丰富与增强,便于拓展现有项目的一些功能. 拓展方法 扩展方法被定义为静态方法,通过实例方法语法进行调用.方法的第一个参数指定该方法作用于哪个类型,并且该参数以 this 修饰符为前缀.仅当使用 using 指令将命名空间显式导入到源代码中之后,扩展方法才可使用. namespace Extensions { public static class StringExtension { public static DateTime To

  • Java实现线程安全单例模式的五种方式的示例代码

    目录 饿汉式 枚举单例 懒汉式 DCL 懒汉式 静态内部类懒汉单例 饿汉式 饿汉式:类加载就会导致该单实例对象被创建 // 问题1:为什么加 final // 问题2:如果实现了序列化接口, 还要做什么来防止反序列化破坏单例 public final class Singleton_hungry implements Serializable { // 问题3:为什么设置为私有? 是否能防止反射创建新的实例? private Singleton_hungry(){} // 问题4:这样初始化是否

  • 详解Java中数组判断元素存在几种方式比较

    1. 通过将数组转换成List,然后使用List中的contains进行判断其是否存在 public static boolean useList(String[] arr,String containValue){ return Arrays.asList(arr).contains(containValue); } 需要注意的是Arrays.asList这个方法中转换的List并不是java.util.ArrayList而是java.util.Arrays.ArrayList,其中java.

  • Java中遍历ConcurrentHashMap的四种方式详解

    这篇文章主要介绍了Java中遍历ConcurrentHashMap的四种方式详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 方式一:在for-each循环中使用entries来遍历 System.out.println("方式一:在for-each循环中使用entries来遍历");for (Map.Entry<String, String> entry: map.entrySet()) { System.out.pr

  • Java中遍历Map集合的5种方式总结

    方式一 通过Map.keySet使用iterator遍历 @Test public void testHashMap1() { Map<Integer, String> map = new HashMap<>(); map.put(001, "Java"); map.put(002, "数据库"); map.put(003, "Vue"); System.out.println(map); // 通过Map.keySet使

  • Java中初始化List集合的八种方式汇总

    目录 1.常规方式 2.Arrays 工具类 3.Collections 工具类 4.Lists 工具类 5.匿名内部类 6.ImmutableList 7.Java8 Stream 8.Java9 List.of 总结 List 是在开发中比较常用的集合,今天总结一下 Java 中初始化 List 的几种方式. 1.常规方式 List<String> list = new ArrayList<>(); list.add("1"); list.add("

随机推荐