多线程的几种状态变换小总结

此文为本人临时按照线程的几个状态转换的思路整理的笔记(思路见下图),正在不断完善修正,水平有限,难免有疏漏不严谨之处,仅供各位参考学习,也欢迎批评指正和交流学习!

一、如何创建线程

创建线程
继承Thread类
extends Thread
实现接口
implements Runnable
implements Callable

创建线程的方法有很多,即要不就选择继承Thread,要不就实现一个接口


知识点二:区分run方法和start方法

start方法

调用线程的***start方法***是创建了新的线程,这时此线程是处于就绪状态,并没有运行。运行操作的是此Thread类调用方法run()来完成的

run方法

调用线程的***run方法***是在主线程中执行该方法,和调用普通方法一样。run方法是多线程的线程体,它包含了要执行的这个线程的内容,Run方法运行结束,此线程终止。然后CPU再调度其它线程。

总之,如果未用start方法开启线程,直接运行run()方法 ,只是普通的对象调用方法,该run方法线程体的内容没有在一个新的线程上运行

知识点三:线程的几种状态:

此图稍有瑕疵,请读者注意辨识

1.新建状态:新创建了一个线程对象

2.就绪状态;在创建线程对象后,调用***start方法***,该线程就处于“可运行线程池”中,等待获得CPU的使用权

以上两种状态代码在上面已贴,此处不贴

3.运行状态:就绪状态的线程得到CPU即进入此状态

4.阻塞状态:线程因为某些原因放弃了CPU的使用权,暂停运行,并等待进入就绪状态

而阻塞又有以下的情况:

等待阻塞:

释放进入等待状态有两种方式:

(1)程序自然离开监视器的范围,即离开synchronized关键字管辖的代码范围

(2)运行的线程执行wait()方法,该线程会释放占用的所有资源,进入等待池

public class MultiThread {

   private static class Thread1 implements Runnable{		
   	@Override
   	public void run() {
   	
   		synchronized(MultiThread.class){
   			System.out.println("thread1 创建...");
   			System.out.println("thread1 就绪中");
   			
   			try{
   				//释放锁有两种方式:(1)程序自然离开监视器的范围,即离开synchronized关键字管辖的代码范围
   				//(2)在synchronized关键字管辖的代码内部调用监视器对象的wait()方法。这里使用wait方法
   				MultiThread.class.wait();
   			}catch(InterruptedException e){
   				e.printStackTrace();
   			}
   			
   			System.out.println("thread1 正在运行 ...");
   			System.out.println("thread1 结束!");
   		}
   	}
   	
   }

进入锁池状态

等待其他线程调用notify()或notifyAll()方法将它唤醒

被唤醒的线程进入锁池,变为锁池状态,准备争夺锁的拥有权,从而进入就绪状态。假如某个线程没有争夺到锁,它仍旧停留在锁池中等待下一次的争夺

private static class Thread2 implements Runnable{
   	@Override
   	public void run() {	
   		//notify方法并不释放锁,即使thread2调用了下面的sleep方法休息10ms,但thread1仍然不会执行
   		//因为thread2没有释放锁,所以Thread1得不到锁而无法执行
   		synchronized(MultiThread.class){
   			System.out.println("thread2 创建...");
   			System.out.println("thread2 此刻唤醒其他wait线程notify other thread can release wait status ...");
   			MultiThread.class.notify();
   		
   			
   			try{
   				System.out.println("thread2 休息    ");
   				Thread.sleep(2000);
   			}catch(InterruptedException e){
   				e.printStackTrace();
   			}
   			
   			System.out.println("thread2 正在运行...");
   			System.out.println("thread2 结束!");
   		}
   	}		
   }


同步阻塞:

运行的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入“锁池”中。


其他阻塞

执行***sleep***()或***join***()方法后,线程不会释放它的“锁标志”---->sleep()状态超时、join()等待线程终止或者超时,线程重新转入就绪状态。

//join()方法会使当前线程等待调用join()方法的线程结束后才能继续执行
public class TestJoin {

   public static void main(String[] args) {
       Thread thread = new Thread(new JoinDemo());
       thread.start();

       for (int i = 0; i < 20; i++) {
           System.out.println("主线程第" + i + "次执行!");
           if (i >= 2)
               try {
                   // t1线程合并到主线程中,主线程停止执行过程,转而执行t1线程,直到t1执行完毕后继续。
                   thread.join();
               } catch (InterruptedException e) {
                   e.printStackTrace();
               }
       }
   }
}

而sleep方法在上面说过了

通过sleep()方法指定等待的时间,让正在执行的线程在指定的时间内暂停执行,进入阻塞状态。但因为它在阻塞时不会释放锁标志,因而锁池里其他线程无法获得锁进入就绪状态


suspend() 和 resume()方法

它们在一起配套使用:suspend()使得一个线程进入阻塞状态,无法自动恢复。只有与它对应的***resume***()才能使线程重新进入可执行状态。

这种特性一般在这种情况下应用:一个线程需要等待另一个线程产生结果。在等的时候,测试发现等待的线程还没产生结果,就让suspend()阻塞对应线程,若结果产生了就调用resume()使其恢复


欢迎大家关注交流!
我的博客地址:GershonHold的博客

我的GitHub地址:GershonHold的Github

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值