JAVA21——线程(状态、基本信息、同步、单例设计模式)

目录

线程状态

停止线程

线程阻塞

线程基本信息

线程同步

单例设计模式

多线程单例模式实现线程安全

单例创建的方式


线程状态

  • 新生状态:
           用new关键字和 Thread类或其子类建立一个线程对象后,该线程对象就处于新生状态。处于新生状态的线程有自己的内存空间,通过调用start方法进入就绪状态(runnable)
  • 就绪状态:
           处于就绪状态的线程已经具备了运行条件,但还没有分配到CPU,处于线程就队列,等待系统为其分配CPU。等待状态并不是执行状态,当系统选定一个等待执行的 Thread对象后,它就会从等待执行状态进入执行状态,系统挑选的动作称之为“cpu调度”,一旦获得CPU,线程就进入运行状态并自动调用自己的run方法
  • 运行状态:
           在运行状态的线程执行自己的run方法中代码,直到调用其他方法而终止、或等待某资源而阻塞或完成任务而死亡。如果在给定的时片内没有执行结束,就会被系统给换下来回到等待执行状态
  • 阻塞状态:
           处于运行状态的线程在某些情况下,如执行了 sleep(睡眠)方法,或等待I/O设备等资源,将让出CPU并暂时停止自己的运行,进入阻塞状态。在阻塞状态的线程不能进入就绪队列。只有当引起阻塞的原因消除时,如睡眠时间已到,或等待的I/O设备空闲下来,线程便转入就绪状态,重新到就绪队列中排队等待,被系统选中后从原来停止的位置开始继续运行
  • 死亡状态:
           死亡状态是线程生命周期中的最后一个阶段。线程死亡的原因有两个,一个是正常运行的线程完成了它的全部工作;另一个是线程被强制性地终止,如通过执行stop或 destroy方法来终止一个线程(不推荐使用这两个方法。前者会产生异常,后者是强制终止,不会释放锁)

停止线程

  1. 自然终止:线程体正常执行完毕
  2. 外部干涉:
    1.线程类中定义线程体使用的标识
    2.线程体使用该标识
    3.提供对外的方法改变标识
    4.外部根据条件调用该方法

eg:

public class Demo01 {
	
	public static void main(String[] args) {
		Study s = new Study();
		new Thread(s).start();
		
		//外部干涉
		for (int i = 0; i < 100; i++) {
			if(i==50){
				s.stop();
			}
			System.out.println("main"+i);
		}
	}
	
}

class Study implements Runnable{
	//1.线程类中定义线程体使用的标识
	private boolean flag = true;
	@Override
	public void run() {
		//2.线程体使用该标识
		while(flag){
			System.out.println("study thread");
		}
		//3.提供对外的方法改变标识
	}
	public void stop(){
		this.flag = false;
	}
}

线程阻塞

  1. join:合并线程
  2. yield:暂停自己的线程   静态方法
  3. sleep:休眠,不释放锁   需要解决并发的问题
    1.与时间相关:倒计时
    2.模拟网络延时

eg:合并线程

/**
 * join:合并线程
 * @author qiao39gs
 *
 */
public class JoinDemo01 extends Thread{
	
	public static void main(String[] args) throws InterruptedException {
		JoinDemo01 demo = new JoinDemo01();
		Thread t = new Thread(demo);	//新生
		t.start();	//就绪
		//cpu调度运行
		
		for (int i = 0; i < 100; i++) {
			if(i==50){
				t.join();	//main阻塞
			}
			System.out.println("main```"+i);
		}
	}
	
	public void run(){
		for (int i = 0; i < 100; i++) {
			System.out.println("join```"+i);
		}
	}
	
}

eg:暂停线程

public class YieldDemo01 extends Thread {

	public static void main(String[] args) {
		YieldDemo01 demo = new YieldDemo01();
		Thread t = new Thread(demo);	//新生
		t.start();	//就绪
		//cpu调度运行
		
		for (int i = 0; i < 1000; i++) {
			if(i%20==0){
				//暂停本线程main
				Thread.yield();
			}
			System.out.println("main```"+i);
		}
	}
	
	public void run(){
		for (int i = 0; i < 1000; i++) {
			System.out.println("yield``````````````````"+i);
		}
	}
}

eg:倒计时

/**
 * 倒计时
 * 1.10个数,一秒内打印一个
 * 2.倒计时
 * @author qiao39gs
 *
 */
public class SleepDemo01 {
	
	public static void main(String[] args) throws InterruptedException {
		Date endTime = new Date(System.currentTimeMillis()+10*1000);
		long end = endTime.getTime();
		while(true){
			//输出
			System.out.println(new SimpleDateFormat("mm:ss").format(endTime));
			//构建下一秒时间
			endTime = new Date(endTime.getTime()-1000);
			//等待一秒
			Thread.sleep(1000);
			//10秒以内继续否则退出
			if(end-10000>endTime.getTime()){
				break;
			}
		}
	}
	
	public static void test1() throws InterruptedException{
		int num = 10;
		while(true){
			System.out.println(num--);
			Thread.sleep(1000);	//暂停
			if(num<=0){
				break;
			}
		}
	}
}

线程基本信息

方法功能
isAlive()判断线程是否还“活”着,即线程是否还未终止
getPriority()获得线程的优先级数值
setPriority()设置线程的优先级数值
setName()给线程一个名字
getName()取得线程的名字
currentThread()取得当前正在运行的线程对象也就是取得自己本身

 eg1:

public class MyThread implements Runnable {
	private boolean flag = true;
	private int num = 0;

	@Override
	public void run() {
		while(flag){
			System.out.println(Thread.currentThread().getName()+"——>"+num++);
		}
	}
	public void stop(){
		this.flag = !this.flag;
	}

}
/**
 * currentThread():当前线程
 * setName:设置名称
 * getName:获取名称
 * isAlive:判断状态
 * @author qiao39gs
 *
 */
public class InfoDemo01 {

	public static void main(String[] args) throws InterruptedException {
		MyThread t1 = new MyThread();
		Thread proxy = new Thread(t1,"AAA");
		proxy.setName("test");
		System.out.println(proxy.getName());
		System.out.println(Thread.currentThread().getName());	//main
		
		proxy.start();
		System.out.println("启动后的状态:"+proxy.isAlive());
		Thread.sleep(20);
		t1.stop();
		Thread.sleep(10);
		System.out.println("停止后的状态:"+proxy.isAlive());
	}
	
}

eg2:

/**
 * 优先级:概率,不是绝对的先后顺序
 * 
 * MAX_PRIORITY		10
 * NORM_PRIORITY	5(默认)
 * MIN_PRIORITY		1
 * 
 * setPriority()
 * getPriority()
 * @author qiao39gs
 *
 */
public class InfoDemo02 {

	public static void main(String[] args) throws InterruptedException {
		MyThread t1 = new MyThread();
		Thread p1 = new Thread(t1,"AAA");
		MyThread t2 = new MyThread();
		Thread p2 = new Thread(t1,"BBB");
		
		p1.setPriority(Thread.MIN_PRIORITY);	//设置优先级
		p2.setPriority(Thread.MAX_PRIORITY);	//设置优先级
		p1.start();
		p2.start();
		
		Thread.sleep(10);
		t1.stop();
		t2.stop();
	}
	
}

线程同步

并发 多个线程访问同一份资源 确保资源安全 ——> 线程安全

线程安全会导致效率低下

  • 由于同一进程的多个线程共享同一片存储空间,在带来方便的同时,也带来了访问冲突这个严重的问题。Java语言提供了专门机制以解决这种冲突,有效避免了同一个数据对象被多个线程同时访问
  • 由于可以通过 private关键字来保证数据对象只能被方法访问,所以只需针对方法提出一套机制,这套机制就是synchronized关键字,它包括两种用法:synchronized方法和synchronized块
  1. 同步方法
    synchronized
  2. 同步块
    synchronized(引用类型|this|类.class){

    }

eg:

public class SynDemo01 {

	public static void main(String[] args) {
		//真实角色
		Web123456 web = new Web123456();
		//代理
		Thread t1 = new Thread(web,"路人甲");
		Thread t2 = new Thread(web,"黄牛乙");
		Thread t3 = new Thread(web,"黄牛丙");
		//启动线程
		t1.start();
		t2.start();
		t3.start();
	}
	
}

/**
 * 线程安全的类
 * @author qiao39gs
 *
 */
class Web123456 implements Runnable{
	private int num = 10;
	private boolean flag = true;
	
	@Override
	public void run() {
		while(flag){
			test5();
		}
	}
	
	//线程不安全,锁定资源不正确
	public void test5(){
		synchronized((Integer) num){
			if(num<=0){
				flag = false;
				return;
			}
			try {
				Thread.sleep(100);	//模拟延时
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			System.out.println(Thread.currentThread().getName()+"抢到了"+num--);
		}
	}
	
	//锁定范围不正确
	public void test4(){
		synchronized(this){
			if(num<=0){
				flag = false;
				return;
			}
		}
		try {
			Thread.sleep(100);	//模拟延时
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println(Thread.currentThread().getName()+"抢到了"+num--);
	}
	
	//线程安全,锁定正确
	public void test3(){
		synchronized(this){
			if(num<=0){
				flag = false;
				return;
			}
			try {
				Thread.sleep(100);	//模拟延时
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			System.out.println(Thread.currentThread().getName()+"抢到了"+num--);
		}
	}
	
	//线程安全,锁定正确
	public synchronized void test2(){
		if(num<=0){
			flag = false;
			return;
		}
		try {
			Thread.sleep(100);	//模拟延时
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println(Thread.currentThread().getName()+"抢到了"+num--);
	}
	
	//线程不安全
	public void test1(){
		if(num<=0){
			flag = false;
			return;
		}
		try {
			Thread.sleep(100);	//模拟延时
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println(Thread.currentThread().getName()+"抢到了"+num--);
	}
}

单例设计模式

单例设计模式:确保一个类只有一个对象

eg: 

/**
 * 单例设计模式:确保一个类只有一个对象
 * @author qiao39gs
 *
 */
public class SynDemo02 {

	public static void main(String[] args) {
		Jvm jvm1 = Jvm.getInstance();
		Jvm jvm2 = Jvm.getInstance();
		System.out.println(jvm1);
		System.out.println(jvm2);
	}
	
}

/*
 * 单例设计模式
 * 确保一个类只有一个对象
 * 懒汉式
 * 1.构造器私有化,避免外部直接创建对象
 * 2.声明一个静态变量
 * 3.创建一个对外的公共的静态方法访问该变量,如果变量没有对象,创建该对象
 */
class Jvm {
	//声明一个私有的静态变量
	private static Jvm instance = null;
	
	//构造器私有化,避免外部直接创建对象
	private Jvm(){
		
	}
	//创建一个对外的公共的静态方法访问该变量,如果变量没有对象,创建该对象
	public static Jvm getInstance(){
		if(null==instance){
			instance = new Jvm();
		}
		return instance;
	}
}

 

多线程单例模式实现线程安全

eg:单例设计模式,class锁定

/**
 * 单例设计模式:确保一个类只有一个对象
 * @author qiao39gs
 *
 */
public class SynDemo02 {

	public static void main(String[] args) {
		JvmThread thread1 = new JvmThread(100);
		JvmThread thread2 = new JvmThread(100);
		
		thread1.start();
		thread2.start();
	}
	
}

class JvmThread extends Thread{
	private long time;
	public JvmThread() {
	}
	public JvmThread(long time) {
		this.time = time;
	}
	@Override
	public void run() {
		System.out.println(Thread.currentThread().getName()+"创建:"+Jvm.getInstance(time));
	}
}

/*
 * 单例设计模式
 * 确保一个类只有一个对象
 * 懒汉式		double checking
 * 1.构造器私有化,避免外部直接创建对象
 * 2.声明一个静态变量
 * 3.创建一个对外的公共的静态方法访问该变量,如果变量没有对象,创建该对象
 */
class Jvm {
	//声明一个私有的静态变量
	private static Jvm instance = null;
	
	//构造器私有化,避免外部直接创建对象
	private Jvm(){
		
	}
	
	//创建一个对外的公共的静态方法访问该变量,如果变量没有对象,创建该对象
	public static Jvm getInstance(long time){
		if(null==instance){		//double checking
			synchronized(Jvm.class){
				if(null==instance){
					try {
						Thread.sleep(time);	//延时,放大错误
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					instance = new Jvm();
				}
			}
		}
		return instance;
	}
	
	public static Jvm getInstance3(long time){
		//效率不高,存在对象也需要等待
		synchronized(Jvm.class){
			if(null==instance){
				try {
					Thread.sleep(time);	//延时,放大错误
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				instance = new Jvm();
			}
			return instance;
		}
	}
	
	public static synchronized Jvm getInstance2(long time){
		//效率不高
		if(null==instance){
			try {
				Thread.sleep(time);	//延时,放大错误
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			instance = new Jvm();
		}
		return instance;
	}
	
	public static Jvm getInstance1(long time){
		if(null==instance){
			try {
				Thread.sleep(time);	//延时,放大错误
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			instance = new Jvm();
		}
		return instance;
	}
}

单例创建的方式

  1. 懒汉式
    1.构造器私有化
    2.声明私有的静态属性
    3.对外提供访问属性的静态方法,确保该对象存在
  2. 饿汉式
    1.构造器私有化
    2.声明私有的静态属性,同时创建对象
    3.对外提供访问属性的静态方法,确保该对象存在

eg1:

public class MyJvm {
	private static MyJvm instance;
	private MyJvm(){
		
	}
	public static MyJvm getInstance(){
		if(null==instance){		//提供效率
			synchronized (MyJvm.class) {
				if(null==instance){	//安全
					instance = new MyJvm();
				}
			}
		}
		return instance;
	}
}

eg2:

class MyJvm3 {
	public static class JVMholder{
		private static MyJvm3 instance = new MyJvm3();
	}
	private MyJvm3(){
		
	}
	public static MyJvm3 getInstance(){
		return JVMholder.instance;	//类在使用的时候加载,延缓加载时间
	}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值