Java线程基础方法及线程分类

本文介绍了Java线程的基础方法,包括start()、run()、yield()、sleep()、join()和interrupt(),并详细解析了它们的实现原理和使用注意事项。同时,讲解了线程的分类,如守护线程和用户线程,以及线程优先级的概念。通过源代码示例,帮助理解线程操作和同步机制。
摘要由CSDN通过智能技术生成

线程基础方法

线程中有这么一些基础方法

  • start():启动线程
  • run():子线程的执行体,常需要重写run()方法
  • yield():线程让步
  • sleep():线程睡眠
  • join():线程同步
  • interrupt():线程中断

start()方法

附源代码:

public synchronized void start() {
		//threadStatus=0时,说明线程处于新建状态
		//此处不为0时,说明线程已启动,因此抛出异常
       if (threadStatus != 0)
            throw new IllegalThreadStateException();
            
        group.add(this);

        boolean started = false;
        try {
            start0();
            started = true;
        } finally {
            try {
                if (!started) {
                    group.threadStartFailed(this);
                }
            } catch (Throwable ignore) {
            }
        }
    }

//此处为第一个try语句中的启动方法
private native void start0();

start()方法中的是用来启动线程的,start()方法是不能被重复调用的。此处仅仅是启动线程,但并没有开始执行代码块,线程状态变成RUNNING(运行)状态时,才会执行代码块。

从上面的源码我们可以看出,线程的启动是依靠start0()方法的,此方法是用关键字native来修饰的,即Java线程的创建是由本地操作系统来完成的,通过调用系统的方法来启动子线程。

run()方法

附源代码:

public void run() {
        if (target != null) {
            target.run();
        }
    }

当run()方法体不为空时,使用target调用run方法。

run()方法是子线程的执行体,和其他普通方法一样,可以被重复调用若在当前线程调用,则不会启动新线程

yield()方法

附源代码:

public static native void yield();

yield()方法是进行线程让步的,可以看出是static和native两个关键字修饰的。

若调用yield方法时,会从RUNNING(运行)状态变成RUNNABLE(就绪)状态,线程所抢占的锁是不会释放的

yield()会让出CPU的执行权,有操作系统决定让给谁,系统会让具有相同优先级的或更高优先级的线程获取CPU的执行权,如果没有相应优先级的线程,当前线程就会立即执行。

※注意点:

  • 调用yield()方法并不等于是当前某个线程进行让步,而是现在正在运行的全部线程暂停让步,因此使用static修饰,且占用的锁不会释放

sleep()方法

附源代码:

//参数为毫秒
public static native void sleep(long millis) throws InterruptedException;
//参数为毫秒和纳秒
public static void sleep(long millis, int nanos)
    throws InterruptedException {
    	//参数校验
        if (millis < 0) {
            throw new IllegalArgumentException("timeout value is negative");
        }
		//参数校验
        if (nanos < 0 || nanos > 999999) {
            throw new IllegalArgumentException(
                                "nanosecond timeout value out of range");
        }
		//四舍五入:0.5毫秒进一||或者总时间小于1毫秒时,进一
        if (nanos >= 500000 || (nanos != 0 && millis == 0)) {
            millis++;
        }

        sleep(millis);
    }

sleep()方法是进行线程睡眠的,会抛出InterruptedException异常,哪个线程调用sleep()方法,哪个线程进入TIME_WAITING(睡眠等待)状态。

sleep()所在的线程休眠期间,线程会释放掉CPU资源给其他线程,但如果当前线程本身持有锁,锁是不会释放的,线程会由RUNNING(运行)状态进入到TIMED_WAITING(睡眠等待)状态,当到达休眠时间或者是被中断掉休眠,就会从睡眠状态进入到就RUNNABLE(就绪)态,从而等待CPU的调用

join()方法

附源代码:

public final void join() throws InterruptedException {join(0);}

public final synchronized void join(long millis) throws InterruptedException {
		//获取当前时间
        long base = System.currentTimeMillis();
        long now = 0;
	
		//参数校验
        if (millis < 0) {
            throw new IllegalArgumentException("timeout value is negative");
        }
		
        if (millis == 0) {
        //isAlive判断子线程是否还在运行,如果参数为0会一直阻塞,线程就会不停的等待,直到其他线程通过notify等方法才能唤醒继续执行
            while (isAlive()) {
                wait(0);
            }
        } else {
            while (isAlive()) {
                long delay = millis - now;
                if (delay <= 0) {
                    break;
                }
                wait(delay);
                now = System.currentTimeMillis() - base;
            }
        }
    }

//Object类下的wait()方法,是线程间通信的方法之一
public final native void wait(long timeout) throws InterruptedException;

join()方法是进行线程同步的,暂停当前线程,等待子线程的执行,也称之为线程合并,join方法特点将并行执行的事情合并为串行执行。执行的本质是使用线程间通信机制来完成线程同步的。

※注意点:

  • 有两个线程:thread1和thread2;thread2在thread1中调用join()方法,此时thread1会暂停,等thread2执行完以后才会执行注意先后顺序
public class thread1 extends Thread{
	public static void main(String[] args) {
				...
				thread2.join();
				...
	}
}

interrupt()方法

附源代码:

public void interrupt() {
        if (this != Thread.currentThread())
            checkAccess();

        synchronized (blockerLock) {
            Interruptible b = blocker;
            if (b != null) {
                interrupt0();           // Just to set the interrupt flag
                b.interrupt(this);
                return;
            }
        }
        interrupt0();
    }
    
private native void interrupt0();

interrupt()是一个普通方法,由对象调用,该对象的线程会进行线程中断,主要用于会抛出InterruptedException的方法:如:slee(),join(),wait()等。

※方法特点:

  • 如果线程当前是可中断的阻塞状态(调用sleep、join、wait等方法会导致线程进入到阻塞状态:WAITING/TIMED_WAITING/BLOCKED),此时会抛出InterruptedException,退出阻塞状态。
  • interrupt()方法不会对正在运行的线程进行中断,直到发生了阻塞后,立即抛出异常,退出阻塞状态。

线程的分类

守护线程

守护线程:也称之为“后台线程”,服务于用户线程,通常用来执行后台任务。如:垃圾回收线程。

守护线程的生命周期:守护线程的生命周期是依赖于用户线程,当用户线程存在,守护线程就会存活,当用户线程生命终止,守护线程的也会随之消亡。

方法

//设置守护线程,默认为FALSE:非守护线程
public final void setDaemon(boolean on) {
        checkAccess();
        if (isAlive()) {
            throw new IllegalThreadStateException();
        }
        daemon = on;
    }
//判断是否为守护线程,FALSE为非守护线程
public final boolean isDaemon() {
        return daemon;
    }

用户线程

用户线程:指不需要内核支持而在用户程序中实现的线程。

用户线程生命周期:主程序结束后,用户线程还会继续执行。

线程优先级

线程优先级:指线程执行的先后顺序。

优先级特点:

  • java线程的优先级并不绝对,它所控制的是执行的优先机会而不是优先的顺序,优先级的决定权在操作系统,java设置的优先级只是被优先执行的概率要高,但不绝对。
  • java中优先级共有10级,分为1-10,数值越大,表明优先级越高,一般普通的线程优先级是5。
//最小优先级
public final static int MIN_PRIORITY = 1;
//普通优先级
public final static int NORM_PRIORITY = 5;
//最大优先级
public final static int MAX_PRIORITY = 10;
  • 优先级具有继承性,如果一个线程B在另一个线程A中创建出来,那么线程B的优先级和线程A保持一致。

方法

//设置优先级
public final void setPriority(int newPriority){}
//获取优先级
public final int getPriority() {return priority;}

关于多线程的有关内容,详戳【Java多线程】,有关上面提到的线程状态,详戳【Java线程的状态及转换】。更多Java内容,详戳主页。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值