1.线程状态
- 新生状态:new Thread ();
- 就绪状态:start() 线程会进入到就绪队列中,等待cpu的调度;
- 运行状态:当就绪队列中的线程被cpu调度,就进入执行状态;
- 阻塞状态:程序无法继续执行,阻塞状态,但是程序并没有结束;
- 终止状态:线程执行结束;
注意:一个线程一旦终止,将无法恢复,如果一个线程阻塞状态解除后,无法直接恢复运行,胡直接进入到就绪状态。
1.1进入就绪状态
- start();
- 阻塞接触,恢复就绪;
- yield 礼让线程;
- cpu调度切换;
1.2进入阻塞状态
- sleep();
- join();
- wait();
- IO操作;
1.3进入终止状态
- 正常执行完毕;
- 添加标识判断——>推荐;
- stop已废弃,并不推荐使用
2.sleep方法
- sleep(ms)线程睡眠,阻塞指定ms时间值;
- 抱着资源睡觉——>对象的资源|锁
- 一个线程执行sleep方法,进入休眠,释放cpu的资源;
sleep方法可以用作模拟网络延迟。
public class ThreadSleepDemo {
public static void main(String[] args) {
new Thread(new SleepDemo()).start();
}
}
class SleepDemo implements Runnable{
@Override
public void run() {
for(int i =10;i>=0;i--){
System.out.println(i);
try {//休眠1秒钟
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
3.yield
yield称作礼让线程;可以给其他线程更多的执行机会(方法其他线程执行的可能性),但是不能决定是否其他线程一定执行,要看cpu的调度。
public class YieldDemo02 implements Runnable{
public static void main(String[] args) {
YieldDemo02 yd = new YieldDemo02();
new Thread(yd,"A").start();
new Thread(yd,"B").start();
}
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"开始执行");
Thread.yield(); //礼让
System.out.println(Thread.currentThread().getName()+"结束执行");
}
}
4.join
join方法可以用来插队,先就绪再插队。
public class ThreadJoinDemo02 {
public static void main(String[] args) {
new Thread(new Fu()).start();
}
}
//Fu类实现Runnable接口
class Fu implements Runnable{
@Override
public void run() {
System.out.println("想吃东西");
System.out.println("给钱让儿子去买东西吃");
//创建一个Zi类的线程
Thread th = new Thread(new Zi());
//调用Zi类线程,Fu类的线程会中断,执行Zi类的线程
th.start();
try {
//如果()中有数字,则表示Fu类线程会等待至多()毫秒数,然后就不等了直接执行
th.join(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("接过东西吃起来");
}
}
class Zi implements Runnable{
@Override
public void run() {
System.out.println("儿子拿到钱去买东西");
System.out.println("路上遇到网吧");
for(int i =1;i<=5;i++){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("时间过了"+i+"秒");
}
System.out.println("赶紧去买东西回家");
}
}
5.getState
Thread类中提供了一个属性:getState()获取一个线程的状态,返回Thread.State类型(枚举类型)。
6.优先级
每一个编程都存在优先级,且一个线程优先级级别为5。
线程的级别分为:1-10,10的优先级最高,1最低。
通过Thread——>getPriority()获取一个线程的优先级
getPriority设置一个线程的优先级
注意:优先级只能放大执行的机会,不代表一定先执行或后执行。
public class ThreadPriorityDemo {
public static void main(String[] args) {
//创建Thread线程,形参为lambda表达式
Thread th = new Thread(()->{
System.out.println("th优先级"+Thread.currentThread().getPriority());
});
//获取线程状态
Thread.State s1 = th.getState();
System.out.println(s1);
Thread th2 = new Thread(()->{
System.out.println("th2优先级"+Thread.currentThread().getPriority());
});
Thread.State s2 = th2.getState();
System.out.println(s1);
Thread th3 = new Thread(()->{
System.out.println("th3优先级"+Thread.currentThread().getPriority());
});
Thread.State s3 = th3.getState();
System.out.println(s1);
//设置各线程的优先级
th.setPriority(Thread.MAX_PRIORITY);
th2.setPriority(5);
th3.setPriority(Thread.MIN_PRIORITY);
//就绪执行线程
th.start();
th2.start();
th3.start();
while(true){
//获取线程状态
System.out.println(th.getState());
System.out.println(th2.getState());
System.out.println(th3.getState());
if(Thread.State.TERMINATED.equals(th.getState())){
System.out.println(th.getState());
break;
}
}
}
}
7.守护线程与用户线程
- 守护线程就是用来守护用户线程,当用户线程执行完毕,守护线程会直接结束;
- 创建线程默认用户线程;
- 垃圾回收期就是一个典型的守护线程;
设置线程为守护线程:
setDaemon(boolean on)将此线程标记为daemon线程或用户线程,true为守护线程,false为用户线程。
public class ThredDaemon {
public static void main(String[] args) {
Thread th = new Thread(()->{
for(int i = 1;i<=10;i++){
System.out.println("我是守护线程"+i);
try {
Thread.sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
//将th设置为守护程序,主程序执行完守护程序也会直接结束
th.setDaemon(true);
th.start();
//以下为主程序
for(int i =1;i<=10;i++){
System.out.println("我是主程序"+i);
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
8.中断线程
- interrupt() 中断此线程,为一个线程添加中断标识;
- interrupted() 测试当前线程是否已被中断,可以判断当前线程是否调用过interrupt()方法,同时复位中断标识,如果调用了,则interrupted()方法返回true,否则返回false;
- isIterrupted()判断线程是否添加过中断标识,但是不会清除这个标识;
如果一个程序执行完毕会自动复位|清除标识;
以上三个方法都不能实现线程的终止,只是添加判断标识,要配合break,return一起使用。
public class InterruptDemo07 {
public static void main(String[] args) {
Thread th = new Thread(()->{
int i = 1;
while(true){
System.out.println("我是th线程"+i++);
if(Thread.interrupted()==true){
System.out.println("结束");
System.out.println("结束之前最后判断状态"+Thread.currentThread().isInterrupted());
break;
}
}
});
th.start();
System.out.println(th.isInterrupted());
//为th线程添加一个中断标识
th.interrupt();
//isInterrupted() 判断th线程是否存在中断标识
for(int i=1;i<=10;i++){
System.out.println(th.isInterrupted());
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
9.synchronized同步锁
9.1同步方法
方法上synchronized修饰;
其中同步的资源是电泳成员方法的对象,同步方法简单,但是单位较大且效率低,而且有可能出现逻辑问题。
public class SynchronizedDemo {
public static void main(String[] args) {
GetTicket gt = new GetTicket();
new Thread(gt,"小王").start();
new Thread(gt,"小张").start();
new Thread(gt,"小李").start();
}
}
class GetTicket implements Runnable{
int tickets = 50;
@Override
public synchronized void run() {//使用synchronized修饰方法
while(tickets>0){
System.out.println(Thread.currentThread().getName()+"抢到了第"+tickets--+"票");
try{
Thread.sleep(100);
}catch(Exception e){
e.printStackTrace();
}
}
}
}
9.2同步块
- 类.class:类的class对象,每一个类在加载到内存的时候都会存在一个属于当前这个类的class对象,唯一且不变。相当于同步了整个类。
public static void main(String[] args) {
GetTicket gt = new GetTicket();
new Thread(gt,"小王").start();
new Thread(gt,"小张").start();
new Thread(gt,"小李").start();
}
}
//同步块(类.class)
class GetTicket implements Runnable{
int tickets = 50;
@Override
public void run() {
while(true){
//synchronized(类.class),相当于修饰了GetTicket这个类的所有对象
synchronized (GetTicket.class){
if(tickets<=0){
break;
}
System.out.println(Thread.currentThread().getName()+"抢到了第"+ tickets-- +"票");
try{
Thread.sleep(100);
}catch(Exception e){
e.printStackTrace();
}
}
}
}
}
- this——>成员方法中默认指代当前调用成员方法的对象;相当于同步了这个类型的某一个对象,锁住了这个对象的所有资源。
public static void main(String[] args) {
GetTicket gt = new GetTicket();
new Thread(gt,"小王").start();
new Thread(gt,"小张").start();
new Thread(gt,"小李").start();
}
}
//同步块(this)
class GetTicket implements Runnable{
int tickets = 50;
@Override
public void run() {
while(true){
synchronized (this){//相当于只修饰了gt这个对象
if(tickets<=0){
break;
}
System.out.println(Thread.currentThread().getName()+"抢到了第"+ tickets-- +"票");
try{
Thread.sleep(100);
}catch(Exception e){
e.printStackTrace();
}
}
}
}
}
- 资源:自定义类型的某一个对象——>new对象的地址;
public static void main(String[] args) {
GetTicket gt = new GetTicket();
new Thread(gt,"小王").start();
new Thread(gt,"小张").start();
new Thread(gt,"小李").start();
}
}
//自定义类
class Tickets {
int tickets =50;
}
//同步块 (自定义引用数据类型的对象)
class GetTicket implements Runnable{
//新建自定义对象
Tickets t = new Tickets();
@Override
public void run() {
while(true){
//同步新建的对象
synchronized (t){
if(t.tickets<=0){
break;
}
System.out.println(Thread.currentThread().getName()+"抢到了第"+ t.tickets-- +"票");
try{
Thread.sleep(100);
}catch(Exception e){
e.printStackTrace();
}
}
}
}
}
10.线程通信
Object类中提供了wait()与notify()、notifyAll()方法,使用前提是在同步环境下;
- wait() 等待,会对应进入到某一个对象的等待池中进行等待,变成阻塞状态,等待被唤醒;
- notify() 唤醒,唤醒某一个对象等待池中正在等待的线程,唤醒某一个,不释放对象锁;
- notify() 唤醒全部;
//红路灯实例
public class SynchronizedDemo02 {
public static void main(String[] args) {
Street s = new Street();
new Thread(new Person(s)).start();
new Thread(new Car(s)).start();
}
}
//街道类,包含两个方法
class Street {
//标记,记录是车通行还是人通行
boolean flag = true;
//车通行的方法 同步
public synchronized void ns (){
//标记为false时车通行
if(flag==false){
flag = true;
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("车走");
//唤醒 人通行的方法
this.notify();
try {
//等待
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
//人通行的方法 同步
public synchronized void we (){
if(flag==true){
flag = false;
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("人走");
this.notify();
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
//人的类
class Person implements Runnable{
private Street street;
//有参构造
public Person(Street street) {
this.street = street;
}
@Override
public void run() {
while(true){
//调用Street类对象的方法
street.we();
}
}
}
//车的类
class Car implements Runnable{
private Street street;
public Car(Street street) {
this.street = street;
}
@Override
public void run() {
while(true){
//调用Street类对象的方法
street.ns();
}
}
}
生产消费者模式——>信号灯法。