start():启动线程

start方法启动一个新线程,start方法首先调用才能创建子线程,不能重复使用

public synchronized void start() {
       group.add(this);

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

    private native void start0();//调用native方法

启动方法是需要底层OS来启动子线程,start是间接启动。

 

native方法说明:

JNI:Java native interface,java本地方法接口(JMM中存在本地方法栈),调度系统本身的提供的非Java代码(C/C++代码)。

 

run():子线程的执行体

整个子线程执行的业务逻辑都在run方法中;单独调用run方法,会在当前的线程中执行run()操作,和普通方法调用是一样的,不会启动子线程,run方法可以重复调用。Thread类中的run方法只是判断任务体Runable是否存在,未做其他业务,继承Thread是需要重写。

 

start()和run()方法的区别:

start()方法是用来启动子线程,start方法启动子线程后自动的来调用run方法。

run()方法是子线程的业务执行体,不能直接调用run方法(通过调用run方法是不能操作子线程的),直接调用和普通方法一样。

 

yield():线程让步

方法在thread类中,是Thread类中静态方法,是用来暂停当前线程的执行,并且让步于其他相同优先级或更高优先级的线程先执行。

方法特点:

1、yield方法让步CPU的资源,让给谁由系统决定的,一般是让给相同优先级或者更高优先级的线程获得执行权,如果没有的话,会执行原来的线程

2、yield让步:会让当前线程由“运行状态”进入到“就绪状态”,就绪状态的线程会按照优先级进行调度,等待CPU的调度。

3、yield让步CPU资源后,线程不会释放锁。

 

join():线程合并(插队)

暂停当前线程执行,等待子线程的执行,也叫做线程合并,join方式是将并行执行的线程合并成串行执行,例:在线程ta中调用tb.join,会暂停ta的执行,先让tb执行完毕,ta才会执行。

方法介绍:

t.join() 允许t线程在当前线程之前执行,待t线程执行结束后当前线程再执行。

t.join(long millis)(时间单位:毫秒)允许t线程在当前线程之前执行,且最长时间millis毫秒之后,当前线程才能执行。

t.join(long millis, int nanos)与t.join(long)一样,只不过可以提供纳秒级的精度。

方法特点:

1、join方法是thread类中的方法,会抛出InterruptedException中断异常

2、当前线程ta中tb.join,tb会执行,ta线程会进入WAITING或TIMED_WAITING状态。

3、当前线程ta中tb.join,则ta线程会释放当前持有的锁join方法实现是通过wait/notify线程通信方式来实现的,wait方法的使用会释放锁。

//一直等待子线程
public final void join() throws InterruptedException {
        join(0);
}
//提供毫秒,纳秒级别的等待时间
public final synchronized void join(long millis, int nanos) throws InterruptedException {
        if (nanos >= 500000 || (nanos != 0 && millis == 0)) {
            millis++;
        }
         //纳秒的处理最终转换为毫秒处理
        join(millis);
    }
//提供毫秒级别的等待时间
public final synchronized void join(long millis)throws InterruptedException {
        if (millis == 0) {
            //millis=0,会一直判断子线程是否结束,否则会一直等待
            while (isAlive()) {
                //线程等待
                wait(0);
            }
        } else {
            //判断子线程是否结束且是否到达指定的毫秒数,否则会等待
            while (isAlive()) {
                long delay = millis - now;
                if (delay <= 0) {
                    break;
                }
                wait(delay);
            }
        }
    }

 

interrupt():中断线程

用来中断当前线程,终止处于“阻塞状态”的线程

方法介绍:

该方法在Thread类中,是一个普通方法,由对象调用该方法。

boolean isInterrupted() 判断是否发送了中断操作, true:发生中断操作  false:未发生中断操作

 

方法特点:

1、如果当前线程是可中断的阻塞状态(join、sleep、wait)等方法会导致线程进入阻塞撞状态:WATING / TIMED_WAITING状态),在任意其他的线程中调用interruprt方法,那么会立即抛出InterruptedException来停止的阻塞状态

2、如果当前线程是可运行状态。调用interruprt方法,线程还是会继续执行,直到发生了sleep、join、wait等方法的调用,才会在进入阻塞之后,随后立即抛出InterruptedException,跳出阻塞状态

 public void interrupt() {
        synchronized (blockerLock) {
            Interruptible b = blocker;
            if (b != null) {
                interrupt0();           // Just to set the interrupt flag 注意这句
                b.interrupt(this);
                return;
            }
        }
        interrupt0();
    }

private native void interrupt0(); //JNI方法,中断操作由系统来提供中断的方式

 

sleep():线程休眠

会让线程休眠,而且哪个线程调用,哪个线程休眠 ,TimeUtil.sleep(long),Thread.sleep、或当前的线程t.sleep,其结果都是当前的线程休眠。

方法介绍:

sleep(long millis)

sleep(long millis, int nanos)

都是提供休眠操作,时间单位粒度不同

sleep 是Thread类提供的方法,会抛出InterruptedException异常

方法特点:

1、sleep休眠期间,会让出CPU使用权,但线程仍然持有锁。(抱着资源睡觉)

2、sleep休眠时间到了之后,不会立即执行,而是线程由“阻塞状态”进入到“就绪状态”。

public static native void sleep(long millis) throws InterruptedException  //JNI 

public static void sleep(long millis, int nanos) throws InterruptedException {
        if (nanos >= 500000 || (nanos != 0 && millis == 0)) {
            millis++;
        }

        sleep(millis);
    }

 

deamon:守护线程

方法介绍:

setDaemon(boolean on) 设置线程为守护线程  true:表示是守护线程    false:非守护线程    默认false

boolean isDaemon():判断当前线程是否是守护线程 true(守护线程)。

Java中的线程主要有两种:用户线程和守护线程。

守护线程和用户线程:

用户线程:一般用户执行的用户级的线程。

守护线程:也叫做后台线程,脱离于终端,用来服务于用户线程。 例如:GC是一个单独的线程处理,GC线程就是一个守护线程。

守护线程的生命周期:

依赖于用户线程,当有用户线程存在,守护线程就会存活,当没有用户线程存在,那守护线程也随之消亡,需要注意的是:Java虚拟机在“用户线程”都结束后会后退出。

 public final void setDaemon(boolean on) {
        checkAccess();
        if (isAlive()) {
            throw new IllegalThreadStateException();
        }
        daemon = on;
    }
    public final boolean isDaemon() {
        return daemon;
    }

 

Priority:线程的优先级

线程优先级,顾名思义:就是来指导线程的执行优先级的

方法介绍:

int getPriority()  获取优先级

setPriority(int newPriority)  设置优先级

方法特点:

1、java线程的优先级并不绝对,它所控制的是执行的机会,也就是说,优先级高的线程执行的概率比较大,而优先级低的线程也并不是没有机会,只是执行的概率相对低一些。

2、Java线程一共有10个优先级,分别为1-10,数值越大,表明优先级越高,一个普通的线程,其优先级为5(默认)线程的优先级具有继承性,如果一个线程B是在另一个线程A中创建的,则B叫做A的子线程,B的初始优先级与A保持一致。

 public final int getPriority() {
        return priority;
    }
public final void setPriority(int newPriority) {
        ThreadGroup g;
        checkAccess();
        if (newPriority > MAX_PRIORITY || newPriority < MIN_PRIORITY) {
            throw new IllegalArgumentException();
        }
        if((g = getThreadGroup()) != null) {
            if (newPriority > g.getMaxPriority()) {
                newPriority = g.getMaxPriority();
            }
            setPriority0(priority = newPriority);
        }
    }

private native void setPriority0(int newPriority); //JNI 

 

posted on 2020-03-12 21:03  CccccDi  阅读(222)  评论(0编辑  收藏  举报