线程:是程序执行的最小单元,依托进程而存在。
进程是资源分配的基本单位,而线程是执行和调度的基本单位, 一个进程可以包含多个线程,多个线程可以共享一块内存空间和一组系统资源。因此线程之间的切换更加节省资源,更加轻量化,因此也称线程是轻量级的进程。
线程的所有状态
New:新生态
线程被创建,但尚未启动时的线程状态。
Thread t=new Thread();线程一旦创建 就进入到了新生态
Runnable:就绪态
调用start()方法线程立即进入就绪状态 ,不代表立即调度执行,等它获得cpu调度之后就会进入运行态。
Blocked:阻塞等待锁的线程状态
表示处于阻塞状态的线程正在等待监视器锁,比如等待执行synchronized代码块或者使用synchronized标记的方法。
Waiting:等待状态
一个处于等待状态的线程正在等待另一个线程执行某个动作。
比如一个线程调用了Object.wait();方法之后,那么他就在等待另一个线程调用notify()/notifyAll()方法。
TIMED_WAITING:计时等待状态
和等待状态类似,只是多了一个超时时间,
比如调用了有超时时间的设置方法 Object.wait(long timeout)或者join(long timeout)等这些方法时才会进入这个状态
TERMINATED:终止状态
表示线程已经执行完成。
常见问题
1.BLOCKED和Waiting的区别(阻塞态和等待状态)
状态形成的调用方法时不一样的。
a.BLOCKED可以看作是当前线程还处在活跃状态,只是在 阻塞等待其他相乘使用完某个锁资源
b.WAITING 则是因为自身调用了Object.wait();或Thread.join()方法又或者LockSupport.park()而进入等待状态只有等待其他线程执行某个特定的动作才能被唤醒。
2.start()和run()方法的区别
从源码上来看:
start():方法属于Thread自身的方法,并且使用了synchronized来保证线程安全
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 */
}
}
}
run() 方法是Runnable的抽象方法,必须由调用类重写这个方法
public void run() {
if (target != null) {
target.run();
}
}
public interface Runnable {
/**
* When an object implementing interface <code>Runnable</code> is used
* to create a thread, starting the thread causes the object's
* <code>run</code> method to be called in that separately executing
* thread.
* <p>
* The general contract of the method <code>run</code> is that it may
* take any action whatsoever.
*
* @see java.lang.Thread#run()
*/
public abstract void run();
}
1.start()方法可以开启多个线程,让线程从新生态转换成就绪态(不能被调用多次否则会抛出异常)
2.run()方法只是一个普通的方法
通俗的来说,启动一个线程是调用start()方法,让线程进入到就绪态,等待cpu的调度之后进如运行,调用run()方法只是调用该线程当中的一个普通方法并不是真正的启动一个线程。
3.线程优先级分为最小优先级,默认优先级,最大优先级
可以理解是:线程抢占CPU时间片的概率,优先级越高,抢占到的概率越大。并不能保证优先级越高就一定是越优先执行。可以通过Thread.setPriority();设置优先级
/**
* The minimum priority that a thread can have.
*/
public final static int MIN_PRIORITY = 1;
/**
* The default priority that is assigned to a thread.
*/
public final static int NORM_PRIORITY = 5;
/**
* The maximum priority that a thread can have.
*/
public final static int MAX_PRIORITY = 10;
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);
}
}
4.线程常用方法
join() 方法:如果在某个当前线程运行时调用other.join();那么当前线程会让出执行权,让other先执行,直到other执行完或者超过超时时间,才会执行当前线程。通过源码来看join()方法底层还是通过wait()方法来实现的。
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) {
while (isAlive()) {
wait(0);
}
} else {
while (isAlive()) {
long delay = millis - now;
if (delay <= 0) {
break;
}
wait(delay);
now = System.currentTimeMillis() - base;
}
}
}
yield() 方法是本地方法,通过源码可以看出是被native修饰的方法也就是说是用c/c++实现的。
1.让当前正在执行的线程暂停 不是阻塞线程,而是将其转为就绪态
2.调用了yield()方法之后,如果没有其他等待执行的线程之后,此时当前线程就会马上恢复执行
sleep(): 指定当前线程等待的毫秒数,进入的是等待超时状态,sleep()时间到达后线程进入就绪态 每个线程都有一个锁 sleep不会释放锁