多线程2

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();
            }
        }
    }
}

版权声明:本文为Love_Beauty原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。