今天是学习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;
- }
- }
- }
- // 定义属性表示票库里的票的数量
- 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
继承关系:实现了Map接口,Hashtable继承Dictionary类
线程安全,效率较低
键和值都不允许为null
HashMap
继承关系:实现了Map接口,继承AbstractMap类
非线程安全,效率较高
键和值都允许为null
前者线程安全,后者非线程安全