java thread target_Java Thread基础知识

Java Thread基础知识

java程序中只有一种途径去启动一个线程,即调用Thread类的start()方法。

java中的线程状态

在Thread类中有一个内部的枚举类State描述了线程的各个状态。

public enum State {

/**

* 线程创建但未启动时会处于此状态

*/

NEW,

/**

* 线程调用start方法,java虚拟机会启动一个线程,被认为是RUNNABLE状态,

* 但此时可能在等待操作系统资源,比如等待cpu的处理器执行,

* 所以可能并没有在操作系统中真正获取到处理器的执行权。

*/

RUNNABLE,

/**

* 获取监视器失败后会处于此状态,比如调用了synchronized方法没有获取到锁时。

*/

BLOCKED,

/**

* 线程在等待另一个线程执行特定操作时,会处于此状态,比如调用了Object.wait(),

* 则会等待另一个线程调用Object.notify()或Object.notifyAll()方法。

* 或者调用thread.join()等待被调用线程的执行结束。

* 调用以下方法会使线程处于此状态

* Object.wait()

*Thread.join()

* LockSupport.park()

* 注意:以上方法都是没有设置设置超时时间

*/

WAITING,

/**

* 相较于WAITING状态,当设置了指定时间时,等待一定时间继续执行,线程处于此状态

* 调用以下方法会使线程处于此状态

* Object.wait( timeout )

* Thread.sleep( timeout )

*Thread.join( timeout )

* LockSupport.parkNanos

*LockSupport.parkUntil

*/

TIMED_WAITING,

/**

* 终止状态,线程执行完成。

*/

TERMINATED;

}

线程常用方法

start

调用start()会开始执行一个线程,此时java虚拟机启动一个线程并调用该类的run()方法。

sleep

使当前线程休眠,放弃cpu使用权则或者放弃竞争cpu使用权,则放弃。

注意:此时如果线程持有锁,不会释放。

join

此方法为线程的实例方法。A线程调用B线程的join方法,A线程将处于等待状态,直到B线程执行完后A线程才继续执行。

interrupt

中断线程。将线程从当前的一个状态中释放出来。当调用该方法时会将线程interrupt状态设置为true。比例调用了线程的 wait、join、sleep时,调用interrupt会中断线程的等待状态,继续执行,此时以上方法会抛出InterruptedException异常。或者线程阻塞于IO操作时,调用该方法会将线程中断,关闭IO操作流。

Object的wait和notify

wait

此方法为Object的方法。调用此方法的前提为必须持有当前obj的锁,如果没有获取到锁而调用该方法会抛出java.lang.IllegalMonitorStateException。将当前运行的线程进入等待状态。并且释放obj的锁。

大多场景为当线程执行到特定逻辑时需要某些条件,当条件不满足时,调用wait方法进行等待。比如生产者/消费者模式,消费者需要等待生产者的数据准备好后才能执行。

notify/notifyAll

此方法为Object的方法。唤醒等待该obj的锁的线程,调用此方法的前提为必须持有当前obj的锁,如果没有获取到锁而调用该方法会抛出java.lang.IllegalMonitorStateException。此时被唤醒的线程需要重新获取该obj的锁才能运行。notify方法会从等待obj的多个线程中选择一个唤醒,notifyAll会唤醒所有的等待线程。

Thread与Runnbale的关系

开发线程类的两种方式

继承Thread,重写run方法

public class TestThread extends Thread {

public static void main(String[] args) {

new TestThread().start();

}

@Override

public void run() {

System.out.println("线程启动");

}

}

实现Runnable接口,调用new Thread(target).start();

public class TestRunnable implements Runnable {

@Override

public void run() {

System.out.println("线程启动");

}

public static void main(String[] args) {

TestRunnable target = new TestRunnable();

new Thread(target).start();

}

}

启动线程的方式

上面代码是我们开发线程常用的两种方式,之所以说是开发不是启动,是因为java中启动线程只能通过Thread类的start方法。

public class Thread implements Runnable {

public synchronized void start() {

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) {

}

}

}

private native void start0();

}

通过源码可以看到 start()调用了start0()方法,start0()是真正让java虚拟机去启动一个线程,此方法为虚拟机内部方法,虚拟机启动线程时会调用run()去执行具体的代码逻辑。所以结论为start方法为让虚拟机真正启动一个线程,而线程的执行逻辑则为run方法。

如有不实,还望指正

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值