Java线程常用的操作方法

2024-08-28 16:08

本文主要是介绍Java线程常用的操作方法,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目标:

 了解设置和取得线程的名称。
了解线程的强制运行。
了解线程的休眠。
了解线程的礼让。
了解线程的中断操作。
具体内容:在多线程中所有的操作方法实际上都是从Thread类开始的。所有的操作都是在Thread类之中的。

线程操作的主要方法

NO	方法名称	类型	描述
1	public Thread(Runnable   target)	构造	接收Runnable接口子类对象,实例化Thread对象
2	public Thread(Runnable target,String  name)	构造	接收Runnable接口子类对象,实例化Thread对象,并设置线程名称
3	public Thread(String  name)	构造	实例化Thread对象,并设置线程名称。
4	public static Thread currentThread()	普通	返回目前正在执行的线程。
5	public final String getName()	普通	返回线程的名称
6	public final int getPriority()	普通	返回线程的优先级
7	public boolean isInterrupted()	普通	判断目前线程是否被中断,如果是,返回true,否则返回false
8	public final boolean isActive()	普通	判断线程是否在活动,如果是返回true,否则返回false
9	public final void join() throws InterruptedException	普通	等待线程死亡
10	public final synchronized void join(long millis) throws  
InterruptedException 	普通	等待millis毫秒后,线程死亡。
11	public void run()	普通	执行线程
12	public  final  void setName()	普通	设定线程名称
13	public final void  setPriority(int newPriority)	普通	设定线程的优先级
14	public static void sleep(long millis) throws
InterruptedException	普通	使目前正在执行的线程休眠millis毫秒
15	public void start()	普通	开始执行线程。
16	public static void yield()	普通	将目前正在执行的线程暂停一次,允许其他线程执行
17	public final void setDaemon(boolean on)	普通	将一个线程设置成后台运行
18	public final void setPriority(int   newPriority)	普通	更改线程的优先级

线程名称

 取得和设置线程名称
在Thread类中,可以通过getName()方法取得线程名称,通过setName()方法设置线程的名称。
线程的名称一般在启动线程前设置,但也允许为已经存在的线程设置名称。允许两个Thread对象有相同的名字,但为了清晰,应该尽量避免这种情况的发生。
另外,如果程序并没有为线程指定名称,则系统会自动的为线程分配一个名称。

线程的名称最好在线程启动前设置,避免重名。
class MyThread implements Runnable{	// 实现Runnable接口public void run(){	// 覆写run()方法for(int i=0;i<3;i++){System.out.println(Thread.currentThread().getName()+ "运行,i = " + i) ;	// 取得当前线程的名字}}
};
public class ThreadNameDemo{public static void main(String args[]){MyThread mt = new MyThread() ;	// 实例化Runnable子类对象new Thread(mt).start() ;		// 系统自动设置线程名称new Thread(mt,"线程-A").start() ;		// 手工设置线程名称new Thread(mt,"线程-B").start() ;		// 手工设置线程名称new Thread(mt).start() ;		// 系统自动设置线程名称new Thread(mt).start() ;		// 系统自动设置线程名称}
};


从执行效果来看,指定的名称会自动出现,如果没有指定会发现线程使用自动编号的方式完成,按照:Thread-0、Thread-1 依次编号,实际上肯定在类中存在一个static属性,用于记录编号。

取得当前线程

程序可以通过currentThread()方法取得当前正在运行的线程对象。
class MyThread implements Runnable{	// 实现Runnable接口public void run(){	// 覆写run()方法for(int i=0;i<3;i++){System.out.println(Thread.currentThread().getName()+ "运行,i = " + i) ;	// 取得当前线程的名字}}
};
public class CurrentThreadDemo{public static void main(String args[]){MyThread mt = new MyThread() ;	// 实例化Runnable子类对象new Thread(mt,"线程").start() ;		// 启动线程mt.run() ;	// 直接调用run()方法}
};

此时发现,程序中由主方法直接通过线程对象调用里面的run()方法,所以输出的结果中包含了一个“main”,此线程就是“mt.run”, 因为调用此语句是由主方法完成的,也就是说实际上主方法本身也是一个线程——主线程。
  问题:既然主方法都是以线程的形式出现的,那么Java运行时到底启动了多少个线程?
  回答:至少启动了两个。从目前的知识上看,每当Java程序执行的时候,实际上都会启动一个JVM,每一个JVM实际上就是在操作系统中启动了一个进程。Java中本身具备了垃圾收集机制,所以Java运行时至少启动两个线程:主线程、GC。

判断线程是否启动

class MyThread implements Runnable{	// 实现Runnable接口public void run(){	// 覆写run()方法for(int i=0;i<3;i++){System.out.println(Thread.currentThread().getName()+ "运行,i = " + i) ;	// 取得当前线程的名字}}
};
public class ThreadAliveDemo{public static void main(String args[]){MyThread mt = new MyThread() ;	// 实例化Runnable子类对象Thread t = new Thread(mt,"线程");		// 实例化Thread对象System.out.println("线程开始执行之前 --> " + t.isAlive()) ;	 // 判断是否启动t.start() ;	// 启动线程System.out.println("线程开始执行之后 --> " + t.isAlive()) ;	 // 判断是否启动for(int i=0;i<3;i++){System.out.println(" main运行 --> " + i) ;}// 以下的输出结果不确定System.out.println("代码执行之后 --> " + t.isAlive()) ;	 // 判断是否启动}
};
      
发现调用start方法之后线程就激活了,如果线程执行任务完毕后就会被关闭。如果没有执行完毕,仍处于激活状态。

线程的强制运行

在线程操作中,可以使用join()方法让一个线程强制运行,线程强制运行期间,其他线程无法运行,必须等待此线程完成之后才可以继续运行。
class MyThread implements Runnable{	// 实现Runnable接口public void run(){	// 覆写run()方法for(int i=0;i<50;i++){System.out.println(Thread.currentThread().getName()+ "运行,i = " + i) ;	// 取得当前线程的名字}}
};
public class ThreadJoinDemo{public static void main(String args[]){MyThread mt = new MyThread() ;	// 实例化Runnable子类对象Thread t = new Thread(mt,"线程");		// 实例化Thread对象t.start() ;	// 启动线程for(int i=0;i<50;i++){if(i>10){try{t.join() ;	// 线程强制运行}catch(InterruptedException e){}}System.out.println("Main线程运行 --> " + i) ;}}
};

线程的休眠

在程序中允许一个线程进行暂时的休眠,直接使用Thread.sleep()方法即可。
class MyThread implements Runnable{	// 实现Runnable接口public void run(){	// 覆写run()方法for(int i=0;i<50;i++){try{Thread.sleep(500) ;	// 线程休眠}catch(InterruptedException e){}System.out.println(Thread.currentThread().getName()+ "运行,i = " + i) ;	// 取得当前线程的名字}}
};
public class ThreadSleepDemo{public static void main(String args[]){MyThread mt = new MyThread() ;	// 实例化Runnable子类对象Thread t = new Thread(mt,"线程");		// 实例化Thread对象t.start() ;	// 启动线程}
};
会发现每隔500毫秒,执行一次。

线程的中断

 当一个线程运行的时候,另外一个线程可以直接通过interrupt()方法 中断其运行状态。
class MyThread implements Runnable{	// 实现Runnable接口public void run(){	// 覆写run()方法System.out.println("1、进入run()方法") ;try{Thread.sleep(10000) ;	// 线程休眠10秒System.out.println("2、已经完成了休眠") ;}catch(InterruptedException e){System.out.println("3、休眠被终止") ;return ; // 返回调用处}System.out.println("4、run()方法正常结束") ;}
};
public class ThreadInterruptDemo{public static void main(String args[]){MyThread mt = new MyThread() ;	// 实例化Runnable子类对象Thread t = new Thread(mt,"线程");		// 实例化Thread对象t.start() ;	// 启动线程try{Thread.sleep(2000) ;	// 线程休眠2秒}catch(InterruptedException e){System.out.println("3、休眠被终止") ;}t.interrupt() ;	// 中断线程执行}
};


后台进程

在Java中,只要有一个程序没有执行完(一个线程在运行),则整个Java的进程就不会消失,所以此时可以设置一个后台线程,这样即使Java进程结束了,此后台线程依然会继续运行,也就是说不影响进程的结束。要想实现这样的操作,直接使用setDaemon()方法即可。
class MyThread implements Runnable{	// 实现Runnable接口public void run(){	// 覆写run()方法while(true){System.out.println(Thread.currentThread().getName() + "在运行。") ;}}
};
public class ThreadDaemonDemo{public static void main(String args[]){MyThread mt = new MyThread() ;	// 实例化Runnable子类对象Thread t = new Thread(mt,"线程");		// 实例化Thread对象t.setDaemon(true) ;	// 此线程在后台运行t.start() ;	// 启动线程}
};
会发现没有打印任何东西,如果设置为false的话则会一直打印,不会结束进程。

线程的优先级

在Java的线程操作中,所有的线程在运行前都会保持在就绪状态,那么此时哪个线程的优先级高,哪个线程就有可能被先执行。

class MyThread implements Runnable{	// 实现Runnable接口public void run(){	// 覆写run()方法for(int i=0;i<5;i++){try{Thread.sleep(500) ;	// 线程休眠}catch(InterruptedException e){}System.out.println(Thread.currentThread().getName()+ "运行,i = " + i) ;	// 取得当前线程的名字}}
};
public class ThreadPriorityDemo{public static void main(String args[]){Thread t1 = new Thread(new MyThread(),"线程A") ;	// 实例化线程对象Thread t2 = new Thread(new MyThread(),"线程B") ;	// 实例化线程对象Thread t3 = new Thread(new MyThread(),"线程C") ;	// 实例化线程对象t1.setPriority(Thread.MIN_PRIORITY) ;	// 优先级最低t2.setPriority(Thread.MAX_PRIORITY) ;	// 优先级最高t3.setPriority(Thread.NORM_PRIORITY) ;	// 优先级居中t1.start() ;	// 启动线程t2.start() ;	// 启动线程t3.start() ;	// 启动线程}
};


主线程的优先级是NORM_PRIORITY 为5 是中等级别。
默认的线程优先级也是NORM_PRIORITY。
程序示例如下:
public class MainPriorityDemo{public static void main(String args[]){System.out.println("主方法的优先级:" + Thread.currentThread().getPriority()) ;	// 取得主方法的优先级System.out.println("MAX_PRIORITY = " + Thread.MAX_PRIORITY) ;System.out.println("NORM_PRIORITY = " + Thread.NORM_PRIORITY) ;System.out.println("MIN_PRIORITY = " + Thread.MIN_PRIORITY) ;}
};

线程的礼让

 在线程操作中,也可以使用yield()方法将一个线程的操作暂时让给其他线程执行。
class MyThread implements Runnable{	// 实现Runnable接口public void run(){	// 覆写run()方法for(int i=0;i<5;i++){try{Thread.sleep(500) ;}catch(Exception e){}System.out.println(Thread.currentThread().getName()+ "运行,i = " + i) ;	// 取得当前线程的名字if(i==2){System.out.print("线程礼让:") ;Thread.currentThread().yield() ;	// 线程礼让}}}
};
public class ThreadYieldDemo{public static void main(String args[]){MyThread my = new MyThread() ;	// 实例化MyThread对象Thread t1 = new Thread(my,"线程A") ;Thread t2 = new Thread(my,"线程B") ;t1.start() ;t2.start() ;}
};


总结:

重点是掌握线程的操作方法,对于这些操作方法只需要从Thread类中查找即可。

线程操作范例

实例要求:设计一个线程操作类,要求可以产生三个线程对象,并可以分别设置三个线程的休眠时间,如下所示:
线程A,休眠10秒。
线程B,休眠20秒
线程C,休眠30秒

分析:已知线程的实现有两种方式,一种是继承Thread类,另外一种是实现Runnable接口。而且在类中应该保存线程名称和休眠时间两个属性。

(一)使用Thread类
在Thread类中直接存在了name属性。
class MyThread extends Thread{private int time ;public MyThread(String name,int time){super(name) ;	// 设置线程名称this.time = time ;	// 设置休眠时间}public void run(){try{Thread.sleep(this.time) ;	// 休眠指定的时间}catch(InterruptedException e){e.printStackTrace() ;}System.out.println(Thread.currentThread().getName() + "线程,休眠"+ this.time + "毫秒。") ;}
};
public class ExecDemo01{public static void main(String args[]){MyThread mt1 = new MyThread("线程A",10000) ;	// 定义线程对象,指定休眠时间MyThread mt2 = new MyThread("线程B",20000) ;	// 定义线程对象,指定休眠时间MyThread mt3 = new MyThread("线程C",30000) ;	// 定义线程对象,指定休眠时间mt1.start() ;	// 启动线程mt2.start() ;	// 启动线程mt3.start() ;	// 启动线程}
};

(二)使用Runnable
如果使用Runnable接口,则类中是没有线程名称存在的,所以应该单独建立一个name属性,以保存线程的名称。
class MyThread implements Runnable{private String name ;private int time ;public MyThread(String name,int time){this.name = name ;	// 设置线程名称this.time = time ;	// 设置休眠时间}public void run(){try{Thread.sleep(this.time) ;	// 休眠指定的时间}catch(InterruptedException e){e.printStackTrace() ;}System.out.println(this.name + "线程,休眠"+ this.time + "毫秒。") ;}
};
public class ExecDemo02{public static void main(String args[]){MyThread mt1 = new MyThread("线程A",10000) ;	// 定义线程对象,指定休眠时间MyThread mt2 = new MyThread("线程B",20000) ;	// 定义线程对象,指定休眠时间MyThread mt3 = new MyThread("线程C",30000) ;	// 定义线程对象,指定休眠时间new Thread(mt1).start() ;	// 启动线程new Thread(mt2).start() ;	// 启动线程new Thread(mt3).start() ;	// 启动线程}
};


这篇关于Java线程常用的操作方法的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1115242

相关文章

Java实现检查多个时间段是否有重合

《Java实现检查多个时间段是否有重合》这篇文章主要为大家详细介绍了如何使用Java实现检查多个时间段是否有重合,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录流程概述步骤详解China编程步骤1:定义时间段类步骤2:添加时间段步骤3:检查时间段是否有重合步骤4:输出结果示例代码结语作

Java中String字符串使用避坑指南

《Java中String字符串使用避坑指南》Java中的String字符串是我们日常编程中用得最多的类之一,看似简单的String使用,却隐藏着不少“坑”,如果不注意,可能会导致性能问题、意外的错误容... 目录8个避坑点如下:1. 字符串的不可变性:每次修改都创建新对象2. 使用 == 比较字符串,陷阱满

Java判断多个时间段是否重合的方法小结

《Java判断多个时间段是否重合的方法小结》这篇文章主要为大家详细介绍了Java中判断多个时间段是否重合的方法,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录判断多个时间段是否有间隔判断时间段集合是否与某时间段重合判断多个时间段是否有间隔实体类内容public class D

IDEA编译报错“java: 常量字符串过长”的原因及解决方法

《IDEA编译报错“java:常量字符串过长”的原因及解决方法》今天在开发过程中,由于尝试将一个文件的Base64字符串设置为常量,结果导致IDEA编译的时候出现了如下报错java:常量字符串过长,... 目录一、问题描述二、问题原因2.1 理论角度2.2 源码角度三、解决方案解决方案①:StringBui

Java覆盖第三方jar包中的某一个类的实现方法

《Java覆盖第三方jar包中的某一个类的实现方法》在我们日常的开发中,经常需要使用第三方的jar包,有时候我们会发现第三方的jar包中的某一个类有问题,或者我们需要定制化修改其中的逻辑,那么应该如何... 目录一、需求描述二、示例描述三、操作步骤四、验证结果五、实现原理一、需求描述需求描述如下:需要在

Java中ArrayList和LinkedList有什么区别举例详解

《Java中ArrayList和LinkedList有什么区别举例详解》:本文主要介绍Java中ArrayList和LinkedList区别的相关资料,包括数据结构特性、核心操作性能、内存与GC影... 目录一、底层数据结构二、核心操作性能对比三、内存与 GC 影响四、扩容机制五、线程安全与并发方案六、工程

ElasticSearch+Kibana通过Docker部署到Linux服务器中操作方法

《ElasticSearch+Kibana通过Docker部署到Linux服务器中操作方法》本文介绍了Elasticsearch的基本概念,包括文档和字段、索引和映射,还详细描述了如何通过Docker... 目录1、ElasticSearch概念2、ElasticSearch、Kibana和IK分词器部署

JavaScript中的reduce方法执行过程、使用场景及进阶用法

《JavaScript中的reduce方法执行过程、使用场景及进阶用法》:本文主要介绍JavaScript中的reduce方法执行过程、使用场景及进阶用法的相关资料,reduce是JavaScri... 目录1. 什么是reduce2. reduce语法2.1 语法2.2 参数说明3. reduce执行过程

C#中读取XML文件的四种常用方法

《C#中读取XML文件的四种常用方法》Xml是Internet环境中跨平台的,依赖于内容的技术,是当前处理结构化文档信息的有力工具,下面我们就来看看C#中读取XML文件的方法都有哪些吧... 目录XML简介格式C#读取XML文件方法使用XmlDocument使用XmlTextReader/XmlTextWr

如何使用Java实现请求deepseek

《如何使用Java实现请求deepseek》这篇文章主要为大家详细介绍了如何使用Java实现请求deepseek功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1.deepseek的api创建2.Java实现请求deepseek2.1 pom文件2.2 json转化文件2.2