java-线程

Posted 嘚吧嘚吧嘚

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java-线程相关的知识,希望对你有一定的参考价值。

一、状态

java线程存在以下几种状态:

1: 创建状态(New):线程被new出来,还未调用start

2: 就绪状态(Runnable):又称为可执行状态,调用线程的start方法后,线程处于就绪状态,,线程调度程序还未给该线程分配cpu时间片执行。

3: 运行状态(Running):线程调度程序分配cpu时间片来执行线程代码。

4: 阻塞状态(Blocked):线程在运行过程中由于某种原因暂停运行进入阻塞状态,只有满足条件后进入就绪状态,获取cpu后才能再次进入运行状态。

阻塞的情况分三种:

A:等待阻塞(wait):调用wait()方法,与synchroined一起使用,线程进入对象等待池,释放synchroined的锁,处于阻塞状态。当有其他线程notify,notifyAll后线

                              进入锁标识等待池,即进入同步阻塞状态。

B:同步阻塞:线程运行过程中需要获取锁,但该锁被其他线程持有,则该线程进入锁标识等待池,处于同步阻塞状态。当线程获取锁之后,线程进入就绪状态。

C:其他阻塞:当线程sleep,或者join,或者发出I/O请求后,知道yield时间到,sleep时间到,join的线程执行完,或者I/O返回后,线程进入就绪状态。

5: 死亡状态(Dead):当线程Run方法退出或者运行出现异常线程停止时,线程就会消亡。

 

二、synchronized的用法

synchronized有两种用法:

一种是写在方法前,如果该方法是静态方法,则获取的锁是类锁,多线程调用该类中所有的实例的该方法都是互斥的。如果该方法不是静态的,则获取的锁是对象锁,多线程调用同一个实例的该方法是互斥的,调用不同实例则不是互斥的。

一种是同步代码块:synchronized(){//....},同样根据方法是否是静态方法区分获取对象锁还是类锁。

 

三、java线程的sleep(),wait(),notify(),yield();

 

1.sleep()使线程休眠一段时间,一段时间结束后,线程进入可执行状态,但并不是立即执行,只是在被排程器调用的时候才执行。在休眠期间,并不释放所持有的“锁”,sleep能够让低优先级的线程有机会运行。

2 . yield( ): 暂停线程的执行,给其它具有相同优先权的线程执行的机会,若此时没有其它线程执行,则此线程继续执行。这个函数并不会释放锁住的对。(线程进入就绪状态,不会释放锁,让同优先级的其他线程有机会运行。但下次可能继续分配cpu时间片,进入运行状态。)

3.  join( ): 等待加入的线程执行完毕才会执行下一个线程。加入的线程通过interrupt( )来唤醒。(让一个线程B加入到一个线程A的尾部,在A运行完前,B不能运行。)

4.  wait( ): 类似sleep( ), 不同的是,wait( )会先释放锁住的对象,然后再执行等待的动作。另外,由于wait( )所等待的对象必须先锁住,因此,它与synchronized一起使用,即必须想获取指定的锁lock,才能lock.wait。wait时,会释放lock,线程进入对象等待池,释放synchroined的锁,处于阻塞状态。当有其他线程notify,notifyAll后线 进入锁标识等待池,即进入同步阻塞状态。注意,这个函数属于Object类。

5.notify:与synchronized一起使用,即必须想获取指定的锁lock,才能lock.notify,synchronized代码块结束后释放锁,通知一个因lock而进入等待阻塞的线程进入同步阻塞状态。

6.notifyAll:与synchronized一起使用,即必须想获取指定的锁lock,才能lock.notifyAll,synchronized代码块结束后释放锁,会通知所有因Lock而进入等待阻塞的线程进入同步阻塞状态。

补:

JAVA多线程中的 wait()方法 与 notify()/notifyAll()方法的用法。

①wait() 与 notify/notifyAll 方法必须在同步代码块中使用

②wait() 与  notify/notifyAll() 的执行过程

③中断 调用wait()方法进入等待队列的 线程

④notify 通知的顺序不能错

⑤多线程中测试某个条件的变化用 if 还是用 while?

 

 

①wait() 与 notify/notifyAll 方法必须在同步代码块中使用

wait() 与 notify/notifyAll() 是Object类的方法,在执行两个方法时,要先获得锁。那么怎么获得锁呢?

在这篇:JAVA多线程之Synchronized关键字--对象锁的特点文章中介绍了使用synchronized关键字获得锁。因此,wait() 与  notify/notifyAll() 经常与synchronized搭配使用,即在synchronized修饰的同步代码块或方法里面调用wait() 与  notify/notifyAll()方法。

 

②wait() 与  notify/notifyAll() 的执行过程

由于 wait() 与  notify/notifyAll() 是放在同步代码块中的,因此线程在执行它们时,肯定是进入了临界区中的,即该线程肯定是获得了锁的。

当线程执行wait()时,会把当前的锁释放,然后让出CPU,进入等待状态。

 当执行notify/notifyAll方法时,会唤醒一个处于等待该 对象锁 的线程,然后继续往下执行,直到执行完退出对象锁锁住的区域(synchronized修饰的代码块)后再释放锁。

从这里可以看出,notify/notifyAll()执行后,并不立即释放锁,而是要等到执行完临界区中代码后,再释放。故,在实际编程中,我们应该尽量在线程调用notify/notifyAll()后,立即退出临界区。即不要在notify/notifyAll()后面再写一些耗时的代码。

 

以上是关于java-线程的主要内容,如果未能解决你的问题,请参考以下文章

java 子线程 回调 主线程

Java多线程 2.线程安全

Java多线程 4.线程池

关于java线程池

Java线程安全和非线程安全

Java线程池