学习java的第二十九天。。。(多线程)

本文介绍了Java多线程中的线程状态、调度、优先级、休眠和礼让,以及在多线程环境下如何确保数据安全。通过示例展示了线程同步的方法,如使用`synchronized`关键字修饰方法或代码块,以避免并发问题。同时,对比了线程安全类型如`StringBuffer`和`HashMap`与非线程安全类型的差异,强调了在并发编程中选择合适线程安全类型的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

今天是学习java的第二十九天,今天学习了多线程

线程的状态

线程调度

线程调度指按照特定机制为多个线程分配CPU的使用权
void setPriority(int  newPriority)    更改线程的优先级
static void sleep(long millis)    在指定的毫秒数内让当前正在执行的线程休眠
void join()    等待该线程终止
static void yield()    暂停当前正在执行的线程对象,并执行其他线程
void interrupt()    中断线程
boolean isAlive()    测试线程是否处于活动状态

线程优先级

线程优先级由1~10表示,1最低,默认优先级为5
优先级高的线程获得CPU资源的概率较大

线程休眠

让线程暂时睡眠指定时长,线程进入阻塞状态
睡眠时间过后线程会再进入可运行状态
    public static void sleep(long millis)
    millis为休眠时长,以毫秒为单位
    调用sleep()方法需处理InterruptedException异常

线程强制运行

使当前线程暂停执行,等待其他线程结束后再继续执行本线程
    millis:以毫秒为单位的等待时长
    nanos:要等待的附加纳秒时长
    需处理InterruptedException异常

线程的礼让

暂停当前线程,允许其他具有相同优先级的线程获得运行机会
该线程处于就绪状态,不转为阻塞状态    public static void yield()
只是提供一种可能,但是不能保证一定会实现礼让

多线程数据共享

public class Site implements Runnable {
	// 定义属性表示票库里的票的数量
	private int count = 10;
	// 定义属性表示用户买到的是第几张票
	private int num = 0;
	@Override
	public void run() {
		// 如果票的属性小于0,就不再买票
		while (true) {
			if (count <= 0) {
				break;
			}
			// 每卖一张票,票的总数要建议,卖的是第几张票,变量要+1
			count--;
			num++;
			// 买票过程中模拟网速缓慢
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			System.out.println(Thread.currentThread().getName() + "买到了第" + num
					+ "张票,还剩" + count + "张票");
		}
	}
}
        Site site1 = new Site();
		Thread t1 = new Thread(site1,"张三");
		Thread t2 = new Thread(site1,"李四");
		Thread t3 = new Thread(site1,"王五");
		t1.start();
		t2.start();
		t3.start();

当多个线程操作共享数据的时候容易出现问题
在一个线程操作这个共享数据的时候,还没有完全操作完毕,线程失去了CPU资源,cpu被另一个线程获取,另外一个线程会接着上一个线程操作的数据继续进行操作,当另外一个线程操作数据完毕之后,第一个线程有获取了CPU资源,此时,第一个线程看到的数据是第二个线程操作后的数据,由此就会引发数据不安全的问题

同步方法 

 使用synchronized修饰的方法控制对类成员变量的访问

访问修饰符 synchronized 返回类型 方法名(参数列表){……}

synchronized 访问修饰符 返回类型 方法名(参数列表){……}

synchronized就是为当前的线程声明一把锁

使用同步方法的网络购票

    public synchronized boolean sale() {
		// 如果票的数量小于0,就不在卖票
		if (count <= 0) {
			return false;
		}

		// 每卖一张票,票的总数要-1,卖的是第几张票变量要+1
		count--;
		num++;
		// 买票过程中模拟网速缓慢
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println(Thread.currentThread().getName() + "买到了第" + num
				+ "张票,还剩余" + count + "张票");

		return true;
	}

    // 定义属性表示票库里的票的数量
	private int count = 10;
	// 定义属性表示用户买到的是第几张票
	private int num = 0;
	@Override
	public void run() {
		while (true) {
			if(!sale()){
				break;
			}
		}
	}

 使用synchronized关键字修饰的代码块

    // 定义属性表示票库里的票的数量
	private int count = 10;
	// 定义属性表示用户买到的是第几张票
	private int num = 0;

	@Override
	public void run() {
		while (true) {
			synchronized (this) {
				// 如果票的数量小于0,就不在卖票
				if (count <= 0) {
					break;
				}

				// 每卖一张票,票的总数要-1,卖的是第几张票变量要+1
				count--;
				num++;
				// 买票过程中模拟网速缓慢
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				System.out.println(Thread.currentThread().getName() + "买到了第"
						+ num + "张票,还剩余" + count + "张票");
			}
		}
	}

 

线程安全的类型

 为达到安全性和效率的平衡,可以根据实际场景来选择合适的类型

常见类型的对比

Hashtable  &&  HashMap

    Hashtable
        继承关系:实现了Map接口,Hashtable继承Dictionary类
        线程安全,效率较低
        键和值都不允许为null
    HashMap
        继承关系:实现了Map接口,继承AbstractMap类
        非线程安全,效率较高
        键和值都允许为null

StringBuffer  &&  StringBuilder

    前者线程安全,后者非线程安全

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

放在糖果旁的是我很想回忆的甜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值