Java的多线程基于Thread,我们先看看Thread的继承关系
public class Thread implements Runnable
可以看到Thread基础了Runnable接口,Runnable接口仅仅有run方法,用于实现线程逻辑。
启动线程-start方法
启动线程需要调用start方法。备注,不要使用run方法,run方法仅仅是执行Runnable实例中的run方法,是同步的。
1)start方法使用synchronized关键词修饰,保证同一时间仅执行一次
2)使用synchronized并不能保证线程多次调用,需要使用threadStatus 记录线程状态,仅仅为Thread.State.NEW才可启动
3)使用Runnable时,主线程无法获取子线程的异常
public synchronized void start() {
/**
* This method is not invoked for the main method thread or "system"
* group threads created/set up by the VM. Any new functionality added
* to this method in the future may have to also be added to the VM.
*
* A zero status value corresponds to state "NEW".
*/
if (threadStatus != 0)
throw new IllegalThreadStateException();
/* Notify the group that this thread is about to be started
* so that it can be added to the group's list of threads
* and the group's unstarted count can be decremented. */
group.add(this);
boolean started = false;
try {
start0();
started = true;
} finally {
try {
if (!started) {
group.threadStartFailed(this);
}
} catch (Throwable ignore) {
/* do nothing. If start0 threw a Throwable then
it will be passed up the call stack */
}
}
}
用户线程和守护线程
守护线程,是指在程序运行的时候在后台提供一种通用服务的线程,比如垃圾回收线程就是一个很称职的守护者,并且这种线程并不属于程序中不可或缺的部分。因此,当所有的非守护线程结束时,程序也就终止了,同时会杀死进程中的所有守护线程。反过来说,只要任何非守护线程还在运行,程序就不会终止。
我们在创建thread的时候默认为用户线程,如果要设置为守护线程,需要调用setDaemon方法
thread.setDaemon(true); //必须在start前调用
需要注意的是:
1)在Daemon线程中产生的新线程也是Daemon的
2)守护线程应该永远不去访问固有资源,如文件、数据库,因为它会在任何时候甚至在一个操作的中间发生中断。