java实现线程的三种方式, stop()和suspend()方法为何不推荐使用

2024-06-22 17:32

本文主要是介绍java实现线程的三种方式, stop()和suspend()方法为何不推荐使用,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • 1 线程的实现
    • 1.1 继承Thread类
    • 1.2 实现Runnable类
    • 1.3 继承和实现区别
    • 1.4 线程池写法
  • 2 stop和suspend方法

1 线程的实现

java5以前,有如下两种:
有两种实现方法,分别使用new Thread()new Thread(runnable)形式,第一种直接调用thread的run方法,所以,我们往往使用Thread子类,即new SubThread()。第二种调用runnablerun方法。分别是继承Thread类与实现Runnable接口

其实,创建线程与创建普通的类的对象的操作是一样的,而线程就是Thread类或其子类的实例对象。每个Thread对象描述了一个单独的线程。要产生一个线程,有两种方法:

  • 需要从Java.lang.Thread类派生一个新的线程类,重载它的run()方法;
  • 实现Runnalbe接口,重载Runnalbe接口中的run()方法。

为什么Java要提供两种方法来创建线程呢?它们都有哪些区别?相比而言,哪一种方法更好呢?
Java中,类仅支持单继承,也就是说,当定义一个新的类的时候,它只能扩展一个外部类。这样,如果创建自定义线程类的时候是通过扩展Thread类的方法来实现的,那么这个自定义类就不能再去扩展其他的类,也就无法实现更加复杂的功能。因此,如果自定义类必须扩展其他的类,那么就可以使用实现Runnable接口的方法来定义该类为线程类,这样就可以避免Java单继承所带来的局限性

1.1 继承Thread类

new Thread(){}.start();这表示调用Thread子类对象的run方法,newThread(){}表示一个Thread的匿名子类的实例对象,子类加上run方法后的代码如下:

new Thread(){public void run(){//代码}
}.start();

那么为啥非要使用start();方法启动多线程呢?
JDK的安装路径下,src.zip是全部的 java源程序,通过此代码找到Thread中的start()方法的定义,可以发现此方法中使用了private native void start0();,其中native关键字表示可以调用操作系统的底层函数,那么这样的技术成为JNI技术(java Native Interface

1.2 实现Runnable类

new Thread(newRunnable(){}).start();这表示调用Thread对象接受的Runnable对象的run方法,newRunnable(){}表示一个Runnable的匿名子类的实例对象,runnable的子类加上run方法后的代码如下:

new Thread(newRunnable(){public void run(){//代码}     }).start();

在使用Runnable定义的子类中没有start()方法,只有Thread类中才有。此时观察Thread类,有一个构造方 法:public Thread(Runnable targer)此构造方法接受Runnable的子类实例,也就是说可以通过Thread类来启动Runnable实现的多线程。(start()可以协调系统的资源):

1.3 继承和实现区别

在程序开发中只要是多线程肯定永远以实现Runnable接口为主,因为实现Runnable接口相比
继承Thread类有如下好处:

  • 避免点继承的局限,一个类可以继承多个接口。
  • 适合于资源的共享

不共享资源写法,利用扩展Thread类创建的多个线程,虽然执行的是相同的代码,但彼此相互独立,且各自拥有自己的资源,互不干扰

class MyThread extends Thread{private int ticket=10;public void run(){for(int i=0;i<20;i++){if(this.ticket>0){System.out.println("卖票:ticket"+this.ticket--);}}}
};下面通过三个线程对象,同时卖票:
public class ThreadTicket {public static void main(String[] args) {MyThread mt1=new MyThread();MyThread mt2=new MyThread();MyThread mt3=new MyThread();mt1.start();//每个线程都各卖了10张,共卖了30张票mt2.start();//但实际只有10张票,每个线程都卖自己的票mt3.start();//没有达到资源共享}
}

如果用Runnable就可以实现资源共享,下面看例子:

class MyThread implements Runnable{private int ticket=10;public void run(){for(int i=0;i<20;i++){if(this.ticket>0){System.out.println("卖票:ticket"+this.ticket--);}}}
}public class RunnableTicket {public static void main(String[] args) {MyThread mt=new MyThread();new Thread(mt).start();//同一个mt,但是在Thread中就不可以,如果用同一个实例化对象mt,就会出现异常new Thread(mt).start();//new Thread(mt).start();}};

结果正如前面分析的那样,程序在内存中仅创建了一个资源,而新建的三个线程都是基于访问这同一资源的,并且由于每个线程上所运行的是相同的代码,因此它们执行的功能也是相同的。
可见,如果现实问题中要求必须创建多个线程来执行同一任务,而且这多个线程之间还将共享同一个资源,那么就可以使用实现Runnable接口的方式来创建多线程程序。而这一功能通过扩展Thread类是无法实现的
实现Runnable接口相对于扩展Thread类来说,具有无可比拟的优势。这种方式不仅有利于程序的健壮性,使代码能够被多个线程共享,而且代码和数据资源相对独立,从而特别适合多个具有相同代码的线程去处理同一资源的情况。这样一来,线程、代码和数据资源三者有效分离,很好地体现了面向对象程序设计的思想。因此,几乎所有的多线程程序都是通过实现Runnable接口的方式来完成的

1.4 线程池写法

Java线程池和callable写法深入讲解

Spring线程池ThreadPoolTaskExecutor的使用

2 stop和suspend方法

synchronized关键字修饰同步方法
反对使用stop(),是因为它不安全。它会解除由线程获取的所有锁定,而且如果对象处于一种不连贯状态,那么其他线程能在那种状态下检查和修改它们。结果很难检查出真正的问题所在。

suspend()方法容易发生死锁。调用suspend()的时候,目标线程会停下来,但却仍然持有在这之前获得的锁定。此时,其他任何线程都不能访问锁定的资源,除非被"挂起"的线程恢复运行。对任何线程来说,如果它们想恢复目标线程,同时又试图使用任何一个锁定的资源,就会造成死锁。所以不应该使用suspend(),而应在自己的Thread类中置入一个标志,指出线程应该活动还是挂起。若标志指出线程应该挂起,便用wait()命其进入等待状态。若标志指出线程应当恢复,则用一个notify()重新启动线程。

这篇关于java实现线程的三种方式, stop()和suspend()方法为何不推荐使用的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


原文地址:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.chinasem.cn/article/1084948

相关文章

SpringBoot项目配置logback-spring.xml屏蔽特定路径的日志

《SpringBoot项目配置logback-spring.xml屏蔽特定路径的日志》在SpringBoot项目中,使用logback-spring.xml配置屏蔽特定路径的日志有两种常用方式,文中的... 目录方案一:基础配置(直接关闭目标路径日志)方案二:结合 Spring Profile 按环境屏蔽关

Python实现精准提取 PDF中的文本,表格与图片

《Python实现精准提取PDF中的文本,表格与图片》在实际的系统开发中,处理PDF文件不仅限于读取整页文本,还有提取文档中的表格数据,图片或特定区域的内容,下面我们来看看如何使用Python实... 目录安装 python 库提取 PDF 文本内容:获取整页文本与指定区域内容获取页面上的所有文本内容获取

基于Python实现一个Windows Tree命令工具

《基于Python实现一个WindowsTree命令工具》今天想要在Windows平台的CMD命令终端窗口中使用像Linux下的tree命令,打印一下目录结构层级树,然而还真有tree命令,但是发现... 目录引言实现代码使用说明可用选项示例用法功能特点添加到环境变量方法一:创建批处理文件并添加到PATH1

Java使用HttpClient实现图片下载与本地保存功能

《Java使用HttpClient实现图片下载与本地保存功能》在当今数字化时代,网络资源的获取与处理已成为软件开发中的常见需求,其中,图片作为网络上最常见的资源之一,其下载与保存功能在许多应用场景中都... 目录引言一、Apache HttpClient简介二、技术栈与环境准备三、实现图片下载与保存功能1.

Python中使用uv创建环境及原理举例详解

《Python中使用uv创建环境及原理举例详解》uv是Astral团队开发的高性能Python工具,整合包管理、虚拟环境、Python版本控制等功能,:本文主要介绍Python中使用uv创建环境及... 目录一、uv工具简介核心特点:二、安装uv1. 通过pip安装2. 通过脚本安装验证安装:配置镜像源(可

python判断文件是否存在常用的几种方式

《python判断文件是否存在常用的几种方式》在Python中我们在读写文件之前,首先要做的事情就是判断文件是否存在,否则很容易发生错误的情况,:本文主要介绍python判断文件是否存在常用的几种... 目录1. 使用 os.path.exists()2. 使用 os.path.isfile()3. 使用

LiteFlow轻量级工作流引擎使用示例详解

《LiteFlow轻量级工作流引擎使用示例详解》:本文主要介绍LiteFlow是一个灵活、简洁且轻量的工作流引擎,适合用于中小型项目和微服务架构中的流程编排,本文给大家介绍LiteFlow轻量级工... 目录1. LiteFlow 主要特点2. 工作流定义方式3. LiteFlow 流程示例4. LiteF

使用Python开发一个现代化屏幕取色器

《使用Python开发一个现代化屏幕取色器》在UI设计、网页开发等场景中,颜色拾取是高频需求,:本文主要介绍如何使用Python开发一个现代化屏幕取色器,有需要的小伙伴可以参考一下... 目录一、项目概述二、核心功能解析2.1 实时颜色追踪2.2 智能颜色显示三、效果展示四、实现步骤详解4.1 环境配置4.

canal实现mysql数据同步的详细过程

《canal实现mysql数据同步的详细过程》:本文主要介绍canal实现mysql数据同步的详细过程,本文通过实例图文相结合给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的... 目录1、canal下载2、mysql同步用户创建和授权3、canal admin安装和启动4、canal

Maven 配置中的 <mirror>绕过 HTTP 阻断机制的方法

《Maven配置中的<mirror>绕过HTTP阻断机制的方法》:本文主要介绍Maven配置中的<mirror>绕过HTTP阻断机制的方法,本文给大家分享问题原因及解决方案,感兴趣的朋友一... 目录一、问题场景:升级 Maven 后构建失败二、解决方案:通过 <mirror> 配置覆盖默认行为1. 配置示