Java 并发编程基础之线程状态

现在操作系统中进程的定义:具有独立功能的程序在一个数据集合上的一次运行,是系统进行资源分配和调度的独立单位。

线程:轻量级进程,是系统调度的最小单元,拥有各自的计数器、堆栈和局部变量等属性,并且能够访问共享的内存变量。

Java程序是天生的多线程程序,通过JMX(thredMXBean)查看一个普通的java程序包含哪些线程。使用多线程的优势:
1)更多的处理器核心
2)更快的响应速度
3)多线程编程模型让程序员专注于更好的问题解决

1、线程优先级
Java线程中通过一个整形成员变量控制优先级,优先级范围是1~10,默认为5,优先级高的线程分配时间片数量要多于优先级低的线程,一般偏重计算的线程给予较低的优先级,确保处理器不被独占,有些操作系统不理会java优先级的设定,如MAC OS X 10.10,Ubuntu 14.04.

2、线程的状态

  • NEW:初始状态,线程被创建,未被调用start()方法
  • RUNABLE:运行状态,就绪和运行的统称
  • TIMED_WAITING:超时等待,指定时间内返回(如调用线程的sleep() 方法)(右上BLOCKED)
  • WAITING:等待状态,表示线程进入等待队列(如调用对象的await()方法),需要其他进程做出通知后被唤醒进入阻塞队列(如调用对象的notify()方法)(左下BLOCKED)
  • BLOCKED:阻塞状态,阻塞于锁(synchronized) (右下BLOCKED)
  • TERMINATED:终止
    在这里插入图片描述
    以上三种阻塞状态分别对应以下三种队列:
    等待队列:线程调用对象wait()方法
    同步队列:线程获取对象锁失败或则被notify()唤醒
    其他:线程调用Thread.sleep()方法让出时间片不释放锁

3、Object对象的wait()和notify()
wait():调用线程会挂起自己让出 CPU 时间片,并将自身加入锁定对象的 Wait Set 中,释放对象的监视器锁(monitor)让其他线程可以获得。
notify():方法则会释放监视器锁的同时,唤醒对象 Wait Set 中等待的线程,顺序是随机的不确定。
wait和notify必须配合synchronized使用,而且wait必须在notify前用,wait后就会进入notify所在的线程,notify后唤醒wait所在的线程,但是wait所在的线程仍然没有获取锁,需要等待notify所在的线程释放锁。

4、Thread类的sleep()、yield()方法
Thread.sleep(long) :该方法是属于Thread类的静态方法。其基本语义是使当前运行的线程暂停一段时间。实现细节是把当前线程放入就绪线程队列中,直到睡眠时间到期才可被调度为执行线程(在时间到期前无法被调度为执行线程)。
Thread.yield():该方法暂停当前正在执行的线程,并执行其他线程。但是,实际中无法保证yield()达到让步的目的,因为,让步的线程可能被线程调度程序再次选中

5、方法比较
thread.join():将指定的线程加入到当前线程,可以将两个交替执行的线程合并为顺序执行的线程。比如在线程B中调用了线程A的Join()方法,直到线程A执行完毕后,才会继续执行线程B。

1)sleep()和yield()区别:调用线程的sleep()方法,可以使比其低的优先线程运行;调用线程的yeild()方法,只让给同优先级运行。

2)join()方法是通过调用线程的wait()方法来达到同步的目的。例如:A线程调用B线程的join(),相当于A线程调用B线程wait()方法,A线程进入阻塞状态,直到B线程执行完才继续执行。

3)sleep()和wait()的区别:①sleep()是Thread类中的方法,wait()是Object类中的方法;②sleep()和wait()的执行,线程都将不占用cpu资源,但是sleep()不会释放对象锁,sleep()结束后,线程进入runnable状态,wait()执行后线程进入waitting状态,只有等待其他线程的notify()/notifyall()才能被唤醒重新获得cpu执行时间,如果没有获得对象锁则进入到Blocked 状态。

4)notify()/wait()的区别:notify()作用唤醒请求队列中的一个线程,而notifyall()唤醒请求队列中所有的线程。notify被调用后,不会像wait()一样马上阻塞线程的运行,而是继续运行,直到调度完成或则让出object的锁。正如上面所提,被唤醒的线程才能继续竞争对象锁。

5、demo 样例来解释 Wait 和 Notify 的功能

import java.util.concurrent.TimeUnit;

public class WaitNotify {

    public static void main(String[] args) {

        final Object A = new Object();
        final Object B = new Object();

        Thread t1 = new Thread("t1-thread") {
            @Override
            public void run() {
                synchronized (A) {
                    System.out.println(Thread.currentThread().getName() + "拿到 A 的监视器锁");
                    System.out.println(Thread.currentThread().getName() + "尝试获取 B 的监视器锁");
                    try {
                        System.out.println(Thread.currentThread().getName() + "休眠 2s,不释放 A 的监视器锁");
                        TimeUnit.SECONDS.sleep(2);
                        System.out.println(Thread.currentThread().getName() + "挂起自己,释放 A 的监视器锁");
                        A.wait();
                        System.out.println(Thread.currentThread().getName() + "被唤醒,等待获取 B 的监视器锁");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    synchronized (B) {
                        System.out.println(Thread.currentThread().getName() + "拿到 B 的监视器锁");
                        B.notify();
                    }
                }
            }
        };

        Thread t2 = new Thread("t2-thread") {
            @Override
            public void run() {
                synchronized (B) {
                    System.out.println(Thread.currentThread().getName() + "拿到 B 的监视器锁");
                    System.out.println(Thread.currentThread().getName() + "尝试获取 A 的监视器锁");
                    synchronized (A) {
                        System.out.println(Thread.currentThread().getName() + "拿到 A 的监视器锁");
                        try {
                            System.out.println(Thread.currentThread().getName() + "休眠 2s,不释放 A 的监视器锁");
                            TimeUnit.SECONDS.sleep(2);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        System.out.println(Thread.currentThread().getName() + "挂起自己,释放 A 的监视器锁,唤醒 t0");
                        A.notify();
                    }
                    try {
                        System.out.println(Thread.currentThread().getName() + "休眠 2s,不释放 B 的监视器锁");
                        TimeUnit.SECONDS.sleep(2);
                        System.out.println(Thread.currentThread().getName() + "挂起自己,释放 B 的监视器锁");
                        B.wait();
                        System.out.println(Thread.currentThread().getName() + "被唤醒");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        };

        t1.start();
        t2.start();
    }
}

t1-thread拿到 A 的监视器锁
t2-thread拿到 B 的监视器锁
t1-thread尝试获取 B 的监视器锁
t2-thread尝试获取 A 的监视器锁
t1-thread休眠 2s,不释放 A 的监视器锁
t1-thread挂起自己,释放 A 的监视器锁
t2-thread拿到 A 的监视器锁
t2-thread休眠 2s,不释放 A 的监视器锁
t2-thread挂起自己,释放 A 的监视器锁,唤醒 t0
t2-thread休眠 2s,不释放 B 的监视器锁
t1-thread被唤醒,等待获取 B 的监视器锁
t2-thread挂起自己,释放 B 的监视器锁
t1-thread拿到 B 的监视器锁
t2-thread被唤醒

Process finished with exit code 0
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值