Java多线程 - 线程状态以及各状态之间的转换

定义:

     线程:是指进程中的一个执行流程

     线程与进程的区别:每个进程都需要操作系统为其分配独立的内存地址空间,而同一进程中的所有线程在同一块地址空间中工作,这些线程可以共享同一块内存和系统资源。

     死锁: 当一个线程等待由另一个线程持有的锁,而后者正在等待已被第一个线程持有的锁时,就会发生死锁。

实现方式:

     Java实现多线程的方法有两种,一是继承Thread类、二是实现Runnable接口。

线程状态及其之间的转换:

  •  当一个线程执行了start方法后,不代表这个线程就会立即被执行,只代表这个线程处于可运行的状态,最终由OS的线程调度来决定哪个可运行状态下的线程被执行。
  • 一个线程一次被选中执行是有时间限制的,这个时间段叫做CPU的时间片,当时间片用完但线程还没有结束时,这个线程又会变为可运行状态,等待OS的再次调度;在运行的线程里执行Thread.yeild()方法同样可以使当前线程变为可运行状态。
  • 在一个运行中的线程等待用户输入、调用Thread.sleep()、调用了其他线程的join()方法,则当前线程变为阻塞状态。
  • 阻塞状态的线程用户输入完毕、sleep时间到、join的线程结束,则当前线程由阻塞状态变为可运行状态。
  • 运行中的线程调用wait方法,此线程进入等待队列。
  • 运行中的线程遇到synchronized同时没有拿到对象的锁标记、等待队列的线程wait时间到、等待队列的线程被notify方法唤醒、有其他线程调用notifyAll方法,则线程变成锁池状态。
  • 锁池状态的线程获得对象锁标记,则线程变成可运行状态。
  • 运行中的线程run方法执行完毕或main线程结束,则线程运行结束。

方法简介:

  • Thread.yield()当前运行的线程变成可运行状态。
  • t2.join() 使得当前线程处于阻塞状态直到t2线程执行完毕。
  • Thread.sleep()使得当前线程处于阻塞状态直到sleep的时间结束。
  • wait、notify、notifyAll方法是Object类的方法,其调用环境必须有synchronized的同步块中调用,否则会抛java.lang.IllegalMonitorStateException异常。

sleep() 和yeild()的区别:

     1、sleep()方法会给其他线程运行的机会,而不考虑其他线程的优先级,因此会给较低线程一个运行的机会;yield()方法只会给相同优先级或者更高优先级的线程一个运行的机会。

     2、当线程执行了sleep(long millis)方法后,将转到阻塞状态,参数millis指定睡眠时间;当线程执行了yield()方法后,将转到就绪状态。

     3、sleep()方法声明抛出InterruptedException异常,而yield()方法没有声明抛出任何异常

     4、sleep()方法比yield()方法具有更好的移植性

关于对象锁:

当一个线程试图访问带有synchronized(this)标记的代码块时,必须获得 this关键字引用的对象的锁,有如下两种情况:

     1、 假如这个锁已经被其它的线程占用,JVM就会把这个线程放到本对象的锁池中。本线程进入阻塞状态。锁池中可能有很多的线程,等到其他的线程释放了锁,JVM就会从锁池中随机取出一个线程,使这个线程拥有锁,并且转到就绪状态。

     2、 假如这个锁没有被其他线程占用,本线程会获得这把锁,开始执行同步代码块。 (一般情况下在执行同步代码块时不会释放同步锁,但也有特殊情况会释放对象锁 如在执行同步代码块时,遇到异常而导致线程终止,锁会被释放;在执行代码块时,执行了锁所属对象的wait()方法,这个线程会释放对象锁,进入对象的等待池中)

线程同步的特征:

     1、如果一个同步代码块和非同步代码块同时操作共享资源,仍然会造成对共享资源的竞争。因为当一个线程执行一个对象的同步代码块时,其他的线程仍然可以执行对象的非同步代码块。(所谓的线程之间保持同步,是指不同的线程在执行同一个对象的同步代码块时,因为要获得对象的同步锁而互相牵制)

     2、 每个对象都有唯一的同步锁 

     3、 在静态方法前面可以使用synchronized修饰符。

     4、 当一个线程开始执行同步代码块时,并不意味着必须以不间断的方式运行,进入同步代码块的线程可以执行Thread.sleep()或者执行Thread.yield()方法,此时它并不释放对象锁,只是把运行的机会让给其他的线程。

     5、 Synchronized声明不会被继承,如果一个用synchronized修饰的方法被子类覆盖,那么子类中这个方法不在保持同步,除非用synchronized修饰。

线程安全的类:

     1、 这个类的对象可以同时被多个线程安全的访问。

     2、 每个线程都能正常的执行原子操作,得到正确的结果。

     3、 在每个线程的原子操作都完成后,对象处于逻辑上合理的状态。

释放对象的锁:

    1、 执行完同步代码块就会释放对象的锁

    2、 在执行同步代码块的过程中,遇到异常而导致线程终止,锁也会被释放

    3、 在执行同步代码块的过程中,执行了锁所属对象的wait()方法,这个线程会释放对象锁,进入对象的等待池。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值