并发编程—对Java中的线程进一步了解
线程常用方法和线程的状态
先不说啥上图:
线程的状态只有5种,如上图所示。整个生命周期就是这几种状态的切换。
重要方法说明:
【简单说明后面再做例子说明】
- start():启动线程,使线程进入就绪/可运行状态,等待操作系统的调度。
- join():把指定的线程加入到当前线程,使得线程之间的并行执行变为串行执行。(原理就是使用的wait()方法)
- yield():让出cpu的执行权,将线程从运行转到可运行状态,但是下个时间片,该线程依然有可能被再次选中运行。
- sleep(): 是Thread中的方法,使线程进入休眠【阻塞】状态,不会释放所持有的锁。当过了指定的休眠时间或者调用中断会进入就绪/可运行状态。
- wait():是Object中的方法,使线程进入等待【阻塞】状态,释放自己所持有的锁。使用notify/notifyAll唤醒后,线程进入就绪/可运行状态。
- notify()/notifyAll():Object中的方法,唤醒等待线程,使线程进入就绪/可运行状态
特别说明
run()和start() :run方法就是普通对象的普通方法,只有调用了start()后,Java才会将线程对象和操作系统中实际的线程进行映射,再来执行run方法。
wait():使用时要先获得锁,所以通常和synchronized配合使用。
线程的优先级
取值为1~10,缺省为5,但线程的优先级不可靠,不建议作为线程开发时候的手段。【这个优先级基本没啥用,就不多说了】
守护线程
将线程设置为守护线程:setDaemon(true);
特点
- 和主线程共死
- finally不能保证一定执行
举个栗子
/**
* 守护线程
* 和主线程共死
* finally不能保证一定执行
*/
public static class DaemonThreadTest extends Thread {
@Override
public void run() {
try {
// 获取线程名
String name = Thread.currentThread().getName();
while (!isInterrupted()) {
System.out.println(name + "is running !");
}
} finally {
// 整个程序运行完了,此句话并没有打印到控制台
System.out.println("finally is run !");
}
}
}
public static void main(String[] args) throws InterruptedException {
DaemonThreadTest daemonThread = new DaemonThreadTest();
// 设置名称
daemonThread.setName("DaemonThread");
// 设置为守护线程
daemonThread.setDaemon(true);
// 启动线程
daemonThread.start();
// 将主线程休眠20ms
TimeUnit.MILLISECONDS.sleep(20);
// 这里并没有调用任何中断的方法,但是当主线程运行结束时,子线程【DaemonThread】也运行停止了
}