多线程2

来源:互联网 发布:求一些莆田鞋的淘宝店 编辑:程序博客网 时间:2024/05/19 23:15

synchronized使用
同步代码块:synchronized放在对象前面,限制一段代码的执行。锁可以是任意对象,但多个线程用的必须是同一把锁。
synchronized(锁对象){
需要同步的代码
}
同步方法:synchronized放在方法声明中,表示整个方法是同步方法。锁是this
public synchronized void method(){ }
静态同步方法:synchronized放在静态方法声明中,表示整个方法是同步方法。锁是字节码文件对象,类名.getclass()。
public static synchronized void method(){ }

同步特点:
好处:同步解决了多线程的安全问题
弊端:当线程很多时,每个线程都会判断同步上的锁,很耗费资源,降低程序的执行效率

容器类的线程安全:
可以用synchronized来锁住这个对象:
synchronized(list){
list.add(…);
}
可以使用java.uitl.Collections的synchronizedXXX()方法来返回一个同步化的容器对象
List list = Collections.synchronizedList(new ArrayList());
这种方式在迭代时仍要用synchronized修饰

List list = Collections.synchronizedList(new ArrayList());        ...       synchronized(list) {                  Iterator i = list.iterator();                  while (i.hasNext()) {                    foo(i.next());                 }    }

死锁
产生原因
有同步嵌套,两个线程都在等待对方已经锁定的资源。

public class TestDead {    public static void main(String[] args) {        RichMan man = new RichMan();        man.setName("富翁");        Kidnapper napper = new Kidnapper();        napper.setName("绑匪");        man.start();        napper.start();    }}class Lock {    public static Object obj1 = new Object();    public static Object obj2 = new Object();}//描述富翁class RichMan extends Thread{    @Override    public void run() {        synchronized (Lock.obj1) {            System.out.println("富翁说:你放了我儿子");            try {                Thread.sleep(10);            } catch (InterruptedException e) {                // TODO Auto-generated catch block                e.printStackTrace();            }            synchronized (Lock.obj2) {                System.out.println("富翁说:我给你1000万");            }        }    }}//描述绑匪class Kidnapper extends Thread{    @Override    public void run() {        synchronized (Lock.obj2) {            System.out.println("绑匪说:你给我1000万");            try {                Thread.sleep(10);            } catch (InterruptedException e) {                // TODO Auto-generated catch block                e.printStackTrace();            }            synchronized (Lock.obj1) {                System.out.println("绑匪说:我放了你儿子");            }        }    }}

如何避免死锁:
一个通用的经验法则是:当几个线程都要访问共享资源(锁)A、B、C时,保证使每个线程都按照同样的顺序去访问它们,比如都先访问A,再访问B和C。
此外,Thread类的suspend()方法也很容易导致死锁,因此这个方法已经被废弃了.

线程的等待与唤醒(生产者与消费者问题)
notify(),wait()等是Object中方法,因为锁是任意对象,所有这么方法通过锁来使用
wait和sleep的区别:
1、sleep任何时候都可以调用,但是wait只能用在同步中。
2、sleep可以在规定时间内醒过来,但是wait需要唤醒,等待的时间是不确定。
3、sleep睡眠中不会交出锁,但是wait会交出同步锁。

生产者和消费者模型

package com.qianfeng.producecustomer;/* * 生产者生产6个,消费者6个 * 包子。 * 一个生产者,一个消费者。 * String * StringBuffer:同步的。效率不高 * StringBuilder:不同步的。效率高。很多时候是单线程。 * 扩展: *         线程池的概念。 *     作业: *         1:将生产多个和消费多个,改成集合和数组来实现。 *      */public class TestProduce2 {    public static void main(String[] args) {        MyCustomer customer  = new MyCustomer();        customer.start();        MyProduce produce = new MyProduce();        produce.start();    }}class MyBaozi{    public static int count = 0;    public static final Integer SUM = 6;//总数。}class MyProduce extends Thread{    @Override    public void run() {        while(true){            //先判断。满了就等待。            synchronized (MyBaozi.SUM) {                if(MyBaozi.count>=MyBaozi.SUM){                    //等待                    try {                        MyBaozi.SUM.wait();                    } catch (InterruptedException e) {                        // TODO Auto-generated catch block                        e.printStackTrace();                    }                }                //否则                MyBaozi.count++;                try {                    Thread.sleep((int)(Math.random()*100));                } catch (InterruptedException e) {                    // TODO Auto-generated catch block                    e.printStackTrace();                }                System.out.println("生产者生产了一个包子,现有"+MyBaozi.count+"个包子");                MyBaozi.SUM.notify();            }        }    }}class MyCustomer extends Thread{    @Override    public void run() {        while(true){            synchronized (MyBaozi.SUM) {                if(MyBaozi.count==0){                    try {                        MyBaozi.SUM.wait();                    } catch (InterruptedException e) {                        // TODO Auto-generated catch block                        e.printStackTrace();                    }                }                //消费                MyBaozi.count--;                try {                    Thread.sleep((int)(Math.random()*100));                } catch (InterruptedException e) {                    // TODO Auto-generated catch block                    e.printStackTrace();                }                System.out.println("消费者消费了一个包子,现有"+MyBaozi.count+"个包子");                MyBaozi.SUM.notify();            }        }    }}
原创粉丝点击