Java线程概述

Java线程概述

线程的创建与启动
1、扩展自java.lang.Thread类
Thread类代表线程类,主要的两个方法:
 * run()包含线程运行时所执行的代码,该方法没有声明抛出任何异常,如果产生异常,需要在里面捕捉,或转换为运行时异常
 * start()用于启动线程

说明:
主线程与用户自定义的线程并发执行
多个线程共享同一个对象的实例变量
不要随便覆盖Thread类的start()方法,如果覆盖需要在第一行调用super.start()来启动线程的run()方法
一个线程只能被调用一次,第二次调用会抛出java.lang.IllegalThreadStateException异常


2、实现Runnable接口

3、线程状态转换
 * 新建状态:用new语句创建的线程对象处于新建状态
 * 就绪状态:当一个线程对象,创建后,其他线程调用它的start()方法,该线程就进入就绪状态
 * 运行状态:当调用run()方法后,线程会在CPU上执行,称为运行状态
 * 阻塞状态:线程因为某些原因放弃CPU,暂时停止运行,Java虚拟机不能为线程分配CPU,直到线程重新进入到就绪状态
     3种情况:
 (1)位于对象的等待池中的阻塞状态,调用wait方法
      (2)位于对象锁池中的阻塞状态,线程同步
    (3)其他阻塞状态:IO操作

 * 死亡状态:当线程退出run()方法的执行时,进入死亡状态,该线程结束生命周期。

4、Java虚拟机的线程调用原理:
 线程调度:指接照特定的机制为多个线程分配CPU的使用权。有两种调度模型,
 (1)分时调度模型:指让所有线程轮流获得CPU的使用权,并且平均分配每个线程占用的CPU的时间片
 (2)抢占式调度模型:指优先让就绪队列中优先级较高的线程占用CPU,如果优先级相同,则随机选择一个线程,使其占用CPU,处于运行状态时的线程一直在运行,直到不得不放弃CPU资源。
 * 放弃CPU资源的原因:CPU让线程暂时放弃CPU,转到就绪状态,使其他线程获得运行机会。
   * 当前线程因为某些原因而进入阻塞状态
  * 线程运行结束

 (3)Java线程调度采用抢占有式调度模型。

5、线程的优先级:
 Thread类中的setPriority(int)和getPriority()用来设置优先级范围1-10
 MAX_PRIORITY 取值为10 表示最高优先级
 MIN_PRIORITY 取值为1 表示最低优先级
 NORM_PRIORITY 取值为5 表示默认的优先级
 如果不设置优先级,则线程的默认的优先级为5,如果一个线程创建了另外一个线程,则两个线程具有相同的优先级
 
6、线程休眠:
  Thread类中的静态方法sleep(long millis),当一个线程运行时执行了sleep方法,则线程放弃CPU,转到阻塞状态。
 当线程结束休眠指定的毫秒数后,则进入就绪状态,等待获得CPU。
 线程在休眠时如果被打断,会收到一个InterruptedException异常,一般会转换为Runntime运行时异常将其抛出。

7、线程让步:
 Thread类中的静态方法yield(),如果此时具有相同优先级的线程处于就绪状态,那么将当前线程由运行状态转换为就绪状态,放到就绪队列中,等待下一次执行。

线程休眠与线程让步区别:

 sleep方法会给其他线程运行机会,而不需要考虚优先级,yield方法只会给相同优先级或者更高优先级的线程一个运行机会。
  sleep方法会让线程进入阻塞状态,yield方法会让线程进入到就绪状态
 sleep方法声明抛出了InterruptedException异常,yield方法没有声明抛出任何异常
 
8、线程合并:
 Thread类中的join()方法,表示当前运行线程调用另一个线程的join方法时,当前运行的线程将转到阻塞状态,直到调用了join方法的线程运行结束。
 
9、获得当前线程对象的引用:
 Thread类中的currendThread()静态方未能返回当前线程对象的引用

10、后台线程:
 后台线程称为守候线程,前台线程也称为用户线程,所有的前台线程都结束生命周期,后台线程才会结束生命周期。
 调用Thread类中的setDaemon(true)方法,能将一个线程设置为后台线程,需要启动前设置为后台线程,否则会产生IllegalThreadStateException异常

11、线程同步:
 原子操作:由一系列的操作完成,这些操作会操纵与其他线程共享的资源,为了保证数据的一致性和正确性,一个线程在执行原子操作期间,必须保证线程的同步。
 同步块:synchronized标记
 同步方法

12、同步锁
 每一个Java对象有且只能有一个同步锁,在任何时刻,最多只允许一个线程拥有这把锁
 

 

线程安全的类:
一个线程安全的类必须满足以下条件:
1、这个类的对象可以同时被多个线程安全的访问。
2、每个线程都能正常执行原子操作,得到正确的结果。
3、在每个线程的原子操作都完成后,对象处于逻辑上合理的状态。

单线程环境:指类的对象只会被一个线程访问
多线程环境:指类的同一个对象会被多个线程类同时访问

释放对象的锁:
由于等待一个锁的线程只有在获得这把锁之后,才能恢复运行,在持有锁的线程在不需要锁的时候,要释放锁,以下情况会释放锁:
1、执行完同步代码块,就会释放锁
2、在执行同步代码块的过程中,遇到异常而导致线程终止,锁也会被释放。
3、在执行同步代码块的过程中,执行了锁所属对象的wait()方法,这个线程会被释放锁,进入对象的等待池。

线程不释放锁:
1、在执行同步代码块的过程中,执行了Thread.sleep()方法,当前线程放弃CPU,开始睡眠,在睡眠中不会释放锁
2、在执行同步代码块的过程中,执行了Thread. yield()方法,当前线程放弃CPU,但不会释放锁。
3、在执行同步代码块的过程中,其他线程执行了当前线程对象的suspend()方法,当前线程被暂停,但不会释放锁


线程通信:
不同的线程执行不同的任务,如果这个任务有某种联系,线程之间必须通信,协调完成工作。
java.lang.Object类中,提供了两个方法,用来完成线程通信。
wait():执行该方法的线程释放对象的锁,Java虚拟机把该线程放到该对象的等待池中,该线程将等待其他线程将它唤醒
notify():执行该方法的线程唤醒在对象的等待池中等待的一个线程。Java虚拟机从对象的等待池中随机的选择一线程,把转到对象的锁池中。


1、当t1线程执行对象S的一个同步代码块时,t1线程持有对象s的锁,t2对象在对象s的锁池中等待。
2、t1线程在同步代码块中执行s.wait()方法,t1线程释放对象s的锁,进入对象s的等待池。
3、在对象s的锁池中等待锁的t2获得了对象s2的锁,执行对象s的另一个同步的代码块。
4、t2线程在同步代码块中执行s.notify()方法,Java虚拟机把t1线程从对象s的等待池移到s的锁池中,在那里等待获得锁。
5、t2线程执行完同步块,释放锁,t1线程获得锁,继续同步块的执行。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值