1.什么是线程?
线程是程序内部的顺序控制流,线程有着独立的运行stock和程序计数器,因此线程是程序执行最小单位,java中线程是通过thread类来实现的。
2.创建线程的方式。
(1).通过继承Thread类来创建线程,重写run方法执行自己的逻辑,start()方法开始启动线程
class Test extends Thread{
@Override
public void run(){
for(int i =0;i<100;i++) {
System.out.println("Thread主线程执行第"+i+"次");
}
//System.out.println("继承Thread类");
}
}
(2).通过实现Runnable接口,run()执行线程。
class Test1 implements Runnable{
@Override
public void run() {
for(int i =0;i<100;i++) {
System.out.println("Runnable主线程执行第"+i+"次");
}
//System.out.println("实现Runnable");
}
}
(3).通过实现Callable接口,执行call方法执行线程
class Test3 implements Callable<Boolean> {
@Override
public Boolean call() throws Exception {
for(int i =0;i<100;i++) {
System.out.println("Callable主线程执行第"+i+"次");
}
//System.out.println("实现Callable接口");
return true;
}
}
线程之间是异步执行。
3.线程状态转换
new
创建未启动的线程处于这个状态。
Runnable(可运行)
线程处于运行状态,等待Cpu分配时间片。
blocked(阻塞)
原因通常是线程在等待一个锁,当尝试进入一个synchronized语句块/方法时,锁已经被其他线程占用,就会阻塞,知道另一个线程走完临界区或发现相应的锁对象wait()操作时,它才有机会进入临界区的权利。处于blocked状态的线程即使调用了interrupt()线程也不会中断,即做了一个中断标记,不能唤醒一个处于阻塞状态的线程。
waiting(无限制等待)
ReentrantLock.lock()操作后进入的是WAITING状态,其内部调用的是LockSupport.park()方法
调用了没有设置timeout参数的Object.wait(),thread.join()和LockSupport.park()会让线程无限制等待.
“阻塞”与“等待”的区别:
(1)“阻塞”状态是等待着获取到一个排他锁,进入“阻塞”状态都是被动的,离开“阻塞”状态是因为其它线程释放了锁,不阻塞了;
(2)“等待”状态是在等待一段时间 或者 唤醒动作的发生,进入“等待”状态是主动的
如主动调用Object.wait(),
如无法获取到ReentraantLock,主动调用LockSupport.park(),
如主线程主动调用 subThread.join(),让主线程等待子线程执行完毕再执行离开“等待”状态是因为其它线程发生了唤醒动作或者到达了等待时间
time_waiting(限期等待)
处于这种状态的线程不会被分配cpu执行时间,不过无需等待被其他线程唤醒,在一定的时间会由系统自动唤醒。
以下方法会让线程进入TIMED_WAITING限期等待状态:
(1)Thread.sleep()方法
(2)设置了timeout参数的Object.wait()方法
(3)设置了timeout参数的Thread.join()方法
(4)LockSupport.parkNanos()方法
(5)LockSupport.parkUntil()方法
tremined(结束)
线程终止状态,run执行完了。
效果图如下:
4.总结:
掌握线程的基础知识,并且知道线程状态的转换。