1,线程有哪些状态?
- 创建
- 就绪
- 阻塞
- 运行
- 死亡
2,各状态过程详情
1. 创建
当创建了一个线程对象的时候,就进入了该状态:
Thread t = new Thread( );
2. 就绪
当调用了start( )方法的时候,线程立即进入就绪状态,但是,这不意味着立即被调度执行,所以,此时等待CPU的调度。
3. 运行
当CPU调度执行的时候,进入该状态,线程才开始真正执行线程体里面的代码块,但是,有时候并不会一直等该线程执行完。
4. 阻塞
所以,当调用sleep( ),wait( )或者同步锁定时,线程就进入了阻塞的状态,意味着代码不往下执行了,阻塞事件解除之后,重新进入就绪状态,再次等待CPU的调度。
5. 死亡
线程中断或者结束,一旦进入死亡状态,就不能再次运行。
3,线程的创建
可见文章:线程创建的方式
4,线程的停止
- 我们不建议使用stop( )方法,或者destroy( )方法,这些方法已经被废弃,官方不建议使用
- 推荐线程自己停止
- 推荐使用标志位来进行线程的停止,如:flag == false,则线程终止。 具体实现如下:
public class TestCreate implements Runnable {
private boolean flag = true;
@Override
public void run() {
int count = 0;
while (flag) {
System.out.println("run...... " + count++);
}
}
public void myStop() {
this.flag = false;
}
public static void main(String[] args) {
TestCreate testCreate = new TestCreate();
new Thread(testCreate).start();
for (int i = 0; i < 1000; i++) {
System.out.println("main thread!" + i);
if (i == 900) {
testCreate.myStop();
System.out.println("thread stop!");
}
}
}
}
5,线程休眠
- sleep(时间)指定当前线程阻塞的毫秒数
- sleep存在异常InterruptedException
- sleep时间达到后,线程进入的是就绪状态
- sleep可以模拟网络延时,倒计时等
- 每一个对象都有一个锁,sleep不会释放锁
5.1 使用sleep模拟倒计时
public class TestSleep {
public static void tenDown() throws InterruptedException {
int num = 10;
while (true) {
Thread.sleep(1000);
System.out.println(num--);
if (num <= 0) {
break;
}
}
}
public static void main(String[] args) {
try {
tenDown();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
5.2 使用sleep模拟网络延迟,可以将问题的发生性放大,可快速可见问题所在
public class TestSleepYanchi implements Runnable {
private int ticketcount = 10;
@Override
public void run() {
while (true) {
if (ticketcount <= 0) {
break;
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "get the " + ticketcount-- + " ticket");
}
}
public static void main(String[] args) {
TestSleepYanchi testSleepYanchi = new TestSleepYanchi();
new Thread(testSleepYanchi, "Tom").start();
new Thread(testSleepYanchi, "Jane").start();
new Thread(testSleepYanchi, "Kangkang").start();
}
}
6,线程礼让
- 礼让线程,让当前正在执行的线程暂停,但不阻塞
- 将线程从运行状态转换为就绪状态
- 让CPU重新调度,所以,礼让不一定成功,看CPU的心情 实现如下:
public class TestYield {
public static void main(String[] args) {
MyYield myYield = new MyYield();
new Thread(myYield, "A").start();
new Thread(myYield, "B").start();
}
}
class MyYield implements Runnable {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + " thread start");
Thread.yield();
System.out.println(Thread.currentThread().getName() + " thread end");
}
}
礼让成功:
礼让失败:
7,合并线程join
- 待此线程执行完成之后,再执行其他的线程,其他的线程处于阻塞状态
- 可以想象成插队,想象成为一个VIP线程
- 这个VIP线程可以是新来的,可以是之前就在执行的
public class TestJoin implements Runnable {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("i am VIP....." + i);
}
}
public static void main(String[] args) throws InterruptedException {
TestJoin testJoin = new TestJoin();
Thread thread = new Thread(testJoin);
thread.start();
//main thread
for (int i = 0; i < 1000; i++) {
System.out.println("main thread " + i);
if (i == 200) {
thread.join();//vip is came.....
}
}
}
}