java中多线程的实现方式以及生命周期?

本文介绍了Java中多线程的三种实现方式:继承Thread类、实现Runnable接口和实现Callable接口。详细讨论了线程的生命周期,包括新建、就绪、运行、阻塞和死亡状态,并列举了Thread类的主要方法。还分析了interrupt、interrupted和isInterrupted的区别,以及Thread.sleep()、wait()和yield()方法的不同之处。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言:

Java 给多线程编程提供了内置的支持。一个多线程程序包含两个或多个能并发运行的部分。程序的每一部分都称作一个线程,并且每个线程定义了一个独立的执行路径。

多线程是多任务的一种特别的形式,但多线程使用了更小的资源开销。这里就不得不说到一个和线程相关的另一个术语

- 进程:一个进程包括由操作系统分配的内存空间,包含一个或多个线程。但是一个线程不能独立的存在,它必须是进程的一部分。

一个进程一直运行,直到所有的非守候线程都结束运行后才能结束。

、JAVA多线程的实现有哪几种方式(附带最简单的示例)
1.继承Thread

线程的具体执行体是在run()方法中通过继承了Thread类的类的实例调用start()方法从而执行run()方法

public class ExtendsThreadTest extends Thread{
	public static void main(String[] args) {
        ExtendsThreadTest test = new ExtendsThreadTest();
		test.start();
	}
	@Override
	public void run() {
		System.out.println("这里是执行主体内容");
	}
}

2.实现Runnable接口

线程的具体执行体是在run()方法中通过实现了Runnable接口的类的实例调用start()方法从而执行run()方法

public class ExtendsThreadTest implements Runnable{
	private Thread thread;
	public static void main(String[] args) {
		ExtendsThreadTest test = new ExtendsThreadTest();
		ExtendsThreadTest test2 = new ExtendsThreadTest();
		test.start();
		test2.start();
	}
	public void start(){
		if(thread == null){
			thread = new Thread(this);
			thread.start();
		}
	}
	@Override
	public void run() {
		System.out.println("这里是执行主体内容");
		}
	}

3.实现Callable<V>接口并接收Future

. 创建 Callable接口的实现类并实现 call()方法 call()方法将作为线程执行体并且有返回值

这个call方法中的执行可以通过实现类的构造函数中所传递进来的服务类来调用本身所重写的业务方法

. 创建 Callable实现类的实例使用 FutureTask类来包装 Callable对象 FutureTask对象封装了该 Callable对象的 call()方法的返回值

. 使用 FutureTask对象作为 Thread对象的 target创建并启动新线程

. 调用 FutureTask对象的 get()方法来获得子线程执行结束后的返回值

public class ExtendsThreadTest implements Callable<String>{
	
	public static void main(String[] args) {
		ExtendsThreadTest test = new ExtendsThreadTest();
		FutureTask<String> task = new FutureTask<String>(test);
		new Thread(task).start();
		try {
			String result = task.get();
			System.out.println(result);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ExecutionException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	@Override
	public String call() throws Exception {
		//这里面执行主体内容代码
		return "hello Thread";
	}
	}

、JAVA线程的生命周期
1.新建状态:

使用 new关键字和 Thread类或其子类建立一个线程对象后该线程对象就处于新建状态它保持这个状态直到程序 start()这个线程

2.就绪状态(也称为可运行状态):

当线程对象调用了start()方法之后该线程就进入就绪状态就绪状态的线程处于就绪队列中要等待JVM里线程调度器的调度

3.运行状态:

如果就绪状态的线程获取 CPU资源就可以执行 run(),此时线程便处于运行状态处于运行状态的线程最为复杂它可以变为阻塞状态就绪状态和死亡状态

4.阻塞状态:

如果一个线程执行了sleep(睡眠)、wait、join等方法该线程就从运行状态进入阻塞状态在睡眠时间已到或获得设备资源后可以重新进入就绪状态可以分为三种

    等待阻塞运行状态中的线程执行 wait()方法使线程进入到等待池中为等待阻塞状态,只有其他线程调用notify或notifyAll才能够唤醒从而进入到就绪状态由于notify()只是唤醒一个线程,但我们不能确定具体唤醒的是哪一个线程,因此在实际使用时,一般都用notifyAll()方法,唤醒有所线程。wait和notify方法会对对象的“锁标志”进行操作,所以它们必须在synchronized函数或synchronized block中进行调用,否则编译通过,运行异常。

    同步阻塞线程在获取 synchronized同步锁失败(因为同步锁被其他线程占用),进入锁池等待。

    其他阻塞通过调用线程的 sleep() join()发出了 I/O请求时线程就会进入到阻塞状态sleep()状态超时,join()等待线程终止或超时或者 I/O处理完毕线程重新转入就绪状态

5.死亡状态:

一个运行状态的线程完成任务或者其他终止条件发生时该线程就切换到终止状态

、Thread类的主要运用方法

1 public void start()  使该线程开始执行;Java虚拟机调用该线程的 run方法

2 public void run()  如果该线程是使用独立的 Runnable运行对象构造的则调用该 Runnable对象的 run方法否则该方法不执行任何操作并返回

3 public final void setName(String name)  改变线程名称使之与参数 name相同

4 public final void setPriority(int priority)  更改线程的优先级

5 public final void setDaemon(boolean on)  将该线程标记为守护线程或用户线程

6 public final void join(long millisec)  等待该线程终止的时间最长为 millis毫秒

7 public void interrupt()  中断线程该方法实际上只是设置了一个中断状态当该线程由于下列原因而受阻时这个中断状态就起作用了

(1)如果线程在调用 Object类的 wait()、wait(long) wait(long, int)方法或者该类的 join()、join(long)、join(long, int)、sleep(long) sleep(long, int)方法过程中受阻则其中断状态将被清除它还将收到一个InterruptedException异常这个时候我们可以通过捕获InterruptedException异常来终止线程的执行具体可以通过return等退出或改变共享变量的值使其退出

(2)如果该线程在可中断的通道上的 I/O操作中受阻则该通道将被关闭该线程的中断状态将被设置并且该线程将收到一个 ClosedByInterruptException。这时候处理方法一样只是捕获的异常不一样而已

 

8 public final boolean isAlive()  测试线程是否处于活动状态

9 public static void yield()  暂停当前正在执行的线程对象并执行同等级其他线程

10 public static void sleep(long millisec)  在指定的毫秒数内让当前正在执行的线程休眠暂停执行时间到则自动唤醒),此操作受到系统计时器和调度程序精度和准确性的影响。并不会释放资源。

11 public static boolean holdsLock(Object x)  当且仅当当前线程在指定的对象上保持监视器锁时才返回 true。

12  public static Thread currentThread()  返回对当前正在执行的线程对象的引用

13 public static void dumpStack()  将当前线程的堆栈跟踪打印至标准错误流

14 public final void wait()  当前线程进行等待需要通过手工调用notify()或者notifyAll()方法才能唤醒

、interrupt、interrupted 、isInterrupted区别是什么

1、interrupt方法用于中断线程调用该方法的线程的状态为将被置为"中断"状态

注意线程中断仅仅是置线程的中断状态位不会停止线程需要用户自己去监视线程的状态为并做处理支持线程中断的方法也就是线程中断后会抛出interruptedException的方法就是在监视线程的中断状态一旦线程的中断状态被置为中断状态”,就会抛出中断异常

2、interrupted是作用于当前线程底层方法入参是true,说明返回线程的状态位后要清掉原来的状态位恢复成原来情况),也只有当前线程能够清楚自己的状态位

3、isInterrupted是作用于调用该方法的线程对象所对应的线程。(线程对象对应的线程不一定是当前运行的线程例如我们可以在A线程中去调用B线程对象的isInterrupted方法。),底层方法入参是false,就是直接返回线程的状态位

五、Thread类的sleep()方法和Object类的wait()方法和Object类的yield()方法有什么区别

首先这两个方法都是可以让线程暂停执行,sleep()方法是Thread类的静态休眠方法调用此方法会让当前线程暂停执行指定的时间但是对象的锁依然保持因此休眠时间结束后会自动恢复转到就绪状态等待CPU资源运行

Wait()Object类的方法调用对象的wait()方法会让当前线程暂停执行并放弃对象的锁进入对象的等待池只有调用对象的notify()方法或者notifyAll()方法时才能唤醒等待池中的线程从而进入等锁池如果线程重新获得对象的锁就可以进入就绪状态等待cpu资源运行,所以这个方法是在同步代码块中进行调用。

Yield是一个静态的原生(native)方法,当前正在执行的线程把运行机会交给线程池中拥有相同优先级的线程。但是不能保证使得当前正在运行的线程迅速转换到就绪(可运行)的状态,它仅能使一个线程从运行状态转到可运行状态,而不是等待或阻塞状态

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值