java 多线程总结

来源:互联网 发布:网络改变大脑阅读答案 编辑:程序博客网 时间:2024/05/29 17:18

补充要点:
sleep 没有释放资源

1  wait方法:
        该方法属于Object的方法,wait方法的作用是使得当前调用wait方法所在部分(代码块)的线程停止执行,并释放当前获得的调用wait所在的代码块的锁,并在其他线程调用notify或者notifyAll方法时恢复到竞争锁状态(一旦获得锁就恢复执行)。
        调用wait方法需要注意几点:
        第一点:wait被调用的时候必须在拥有锁(即synchronized修饰的)的代码块中。
        第二点:恢复执行后,从wait的下一条语句开始执行,因而wait方法总是应当在while循环中调用,以免出现恢复执行后继续执行的条件不满足却继续执行的情况。
        第三点:若wait方法参数中带时间,则除了notify和notifyAll被调用能激活处于wait状态(等待状态)的线程进入锁竞争外,在其他线程中interrupt它或者参数时间到了之后,该线程也将被激活到竞争状态。
        第四点:wait方法被调用的线程必须获得之前执行到wait时释放掉的锁重新获得才能够恢复执行。

2  notify方法和notifyAll方法:
        notify方法通知调用了wait方法,但是尚未激活的一个线程进入线程调度队列(即进入锁竞争),注意不是立即执行。并且具体是哪一个线程不能保证。另外一点就是被唤醒的这个线程一定是在等待wait所释放的锁。
        notifyAll方法则唤醒所有调用了wait方法,尚未激活的进程进入竞争队列。

3 synchronized关键字:
        第一点:synchronized用来标识一个普通方法时,表示一个线程要执行该方法,必须取得该方法所在的对象的锁。
        第二点:synchronized用来标识一个静态方法时,表示一个线程要执行该方法,必须获得该方法所在的类的类锁。
        第三点:synchronized修饰一个代码块。类似这样:synchronized(obj) { //code.... }。表示一个线程要执行该代码块,必须获得obj的锁。这样做的目的是减小锁的粒度,保证当不同块所需的锁不冲突时不用对整个对象加锁。利用零长度的byte数组对象做obj非常经济。

4 atomic action(原子操作):
        在JAVA中,以下两点操作是原子操作。但是c和c++中并不如此。
        第一点:对引用变量和除了long和double之外的原始数据类型变量进行读写。
        第二点:对所有声明为volatile的变量(包括long和double)的读写。
        另外:在java.util.concurrent和java.util.concurrent.atomic包中提供了一些不依赖于同步机制的线程安全的类和方法。


5.InterruptedException 何时发生?

在这里使用的interrupt方法,是Thread类的实例方法.执行interrupt方法时,不需要获取Thread实例的锁定.任何线程在任何时刻,都可以调用其它线程的interrupt方法.
当sleep方法的线程被调用interrupt方法时,就会放弃暂停的状态,并抛出InterruptedException.

1)Wait方法与interrupt方法
    同样以上一个例子为例,当t1以wait方法等待时,与sleep一样可以取消.使用interrupt方法,可以对wait中的线程传达"不用等notify/notifyAll了,从等待中出来"的信号.
但是当线程wait时,有一点需要注意的,那就是锁的问题.线程进入等待状态时,会将自己拥有的锁释放,当对wait中的线程调用interrupt方法是,等待线程会重新获取锁,然后再
抛出interruptedException.获取锁定之前,并无法抛出InterruptedException异常.
 
2)Join方法与interrupt方法
  当线程以join方法等待其它线程结束时,一样可以使用interrupt方法取消.因为调用join方法不需要获取锁定.

3)interrupt方法只是改变中断状态而已
   或许有很多人都是这样认为的,当调用了interrupt方法后,目的线程就会抛出InterruptedExceptoin异常,但其实是误解.事实上,interrupt这个方法改变线程的中断状态而已.
所谓中断状态,是用来表示这个线程有没有被中断的状态. 当线程A在执行sleep,wait,join时,另一个线程B调用了interrupt方法,的确这个时候线程A会有InterruptedException
异常抛出.但这其实是在sleep,wait,join这些方法内部会不断检查中断状态的值,而自己抛出的InterruptedException. 如果线程A正在执行一些复杂的计算,那么,就算此时线程
B调用A的interrupt方法,线程A也不会抛出InterruptedException异常,而会继续处理自己后续的操作.当线程执行到sleep,wait,join这些方法,或是没有在线程里自己检查中断
状态,自己抛出InterruptedException,那InterruptedException是不会被抛出的.

4)isInterrupted方法 -- 检查中断状态
  Thread类的实例方法isInterrupted方法可用来检查指定线程的中断状态.当线程为中断状态时,会返回true;而线程为不是中断状态时,会返回false.isInterrupted不会自己改变中断状态.

5)Thread.interrupted方法 -- 检查并清除中断状态
  而Thread.interrupted方法会检查线程的中断状态,并清除线程的状态.当线程的线程为中断状态时,就返回true,若非中断状态时,则返回false.调用Thread.interrupted方法后,中断状态
  会被清除. 除了这个方法以外,没有其它用来清除中断状态的方法.Thread.interrupted方法检查的对象是现在的线程,所以我们无法清除其它线程的中断状态.

 

6.死锁的条件

1)互斥条件

2)请求和保持

3)不剥夺

4)环路等待

 

附网上流传的生产消费者实例

 

package com.dada.test.thread;/** * 生产者(producer)与消费者(consumer)问题 说明事物锁与多线程同步 生产者生产,消费者消费,规则:但当库存为0时,消费者要消费是不行的; * 但当库存为上限(这里是10)时,生产者也不能生产 *  * @author wsq198753@qq.com */public class ObjLock implements Runnable {private Object o = new Object();private int count = 0; // 产品数private int locknum = 0; // 上锁的线程数public ObjLock(int n) {this.count = n;}// 生产public  void produce() {synchronized(o){while (count == 10) {locknum++;try {o.wait();} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}count++;if (locknum > 0)locknum--;o.notify();}}// 消费public synchronized void consume() {synchronized(o){while (count == 0) {locknum++;try {o.wait();} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}count--;if (locknum > 0)locknum--;o.notify();}}public void run() {while (true) {if (Thread.currentThread().getName().substring(0, 8).equals("producer"))produce();else if (Thread.currentThread().getName().substring(0, 8).equals("consumer"))consume();System.out.println(Thread.currentThread().getName() + ": " + count+ " ,locknum: " + locknum);}}}


 

package com.dada.test.thread;public class TestObjLock {public static void main(String[] args) {  ObjLock ol = new ObjLock(1);  Thread th1 = new Thread(ol,"producer");  Thread th2 = new Thread(ol,"consumer");  Thread th3 = new Thread(ol,"producer");  Thread th4 = new Thread(ol,"producer");  Thread th5 = new Thread(ol,"producer");  Thread th6 = new Thread(ol,"producer");    th1.start();  th2.start();  th3.start();  th4.start();  th5.start();  th6.start(); }}