黑马程序员---2015.6.18笔记---线程--死锁

------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------

1.同步函数使用的锁是this锁

2.如果同步函数被静态修饰后,使用的锁是什么?
        静态进内存是,内存中没有本类对象,但是一定有该类对象对应的字节码文件对象
        类名.class 该对象的类型是Class
        
        静态的同步方法,使用的锁是该方法所在类的字节码文件对象 类名.class
3.懒汉式:延迟加载的单例设计模式
    缺点:多线程访问时,可能引起线程安全问题
    解决方式:加同步锁(而且用双重判断提高效率)        
      
 /*    饿汉式(解决了线程安全问题)
        */
        class Single
        {
            private static Single s = null;
            private Single(){}
            
            public static Single getInstance()
            {
                if(s == null)
                {
                    /* 如果线程B停在这里 s = null;
                       而线程A 在锁里执行完 s = new Single();
                       但是线程B 获得锁后,还会再次 new Single();
                        synchronized(Single.class)
                    {
                            s = new Single();
                    }
                    
                    
                */
                    synchronized(Single.class)
                    {
                        if(s == null)
                        {
                            s = new Single();
                        }
                    }
                }
            }
        }


        4.
/*
            死锁的一个例子
        */
        
        class DeadLockDemo
        {
            public static void main(String[] args)
            {
                Thread t1 = new Thread(new DeadLock(true));
                Thread t2 = new Thread(new DeadLock(false));
                t1.start();
                t2.start();
            }
        }
        
        class DeadLock implements Runnable
        {
            private boolean flag = true;
            public DeadLock (boolean flag)
            {
                    this.flag = flag;
            }
            
            public void run()
            {
                    if(flag) {
                        synchronized(MyLock.o1)
                        {
                            System.out.println("if o1")    ;
                            synchronized(MyLock.o2)
                            {
                                System.out.println("if o2")    ;
                            }
                        }
                    } else {
                        synchronized(MyLock.o2)
                        {
                            System.out.println("else o2")    ;
                            synchronized(MyLock.o1)
                            {
                                System.out.println("else o1")    ;
                            }
                        }
                    }
                
            }
        }
        
        class MyLock
        {
            static Object o1 = new Object();
            static Object o2 = new Object();    
        }    


5.线程间通信
            其实就是多个线程在操作同一个资源,但是操作的动作不同。
6.wait() ,notify();    notifyAll();
    都使用在同步中,因为要对持有监视器(锁)的线程操作        
    所以要使用在同步中,因为只有同步才具有锁。
    
    为什么这些操作线程的方法要定义在Object类中呢?
    因为这些方法在操作同步线程时,都必须要标识他们所操作线程只有的锁。
    只有同一个锁上的被等待线程,可以被同一个锁上notify唤醒、
    不可以对不同锁中的线程进行唤醒。
    也就是说,等待和唤醒必须是同一锁。
    而锁可以使任意对象,所以可以被任意对象调用的方法定义在Object中。
7.
/*
        对于多个生产者和消费者时
        为什么要定义while判断标记?
        原因:让被唤醒的线程再一次判断标记。
        
        为什么定义notifyAll
        因为需要唤醒对方线程。
        因为只有notify,容易出现只唤醒本方线程的情况,导致程序中的所有线程都等待。
    */
    class ProducerConsumer
    {
        public static void main(String[] args)
        {
            Resource r = new Resource();
            Producer p = new Producer(r);
            Consumer c = new Consumer(r);
            Thread t1 = new Thread(p);
            t1.start();
            Thread t2 = new Thread(c);
            t2.start();
            Thread t3 = new Thread(p);
            t3.start();
            Thread t4 = new Thread(c);
            t4.start();
        }
    }
    
    class Resource
    {
        private String name;
        private int count = 1;
        private boolean flag = false;
        
        public synchronized void set(String name)
        {
            //当等待结束后,会再次判断flag
            while(flag)
            {
                try{this.wait();}catch(Exception e){}
            }    
            this.name = name+"---"+(count++);
            System.out.println(Thread.currentThread().getName()+"生产者--"+this.name);
            flag = true;
            this.notifyAll();
        }    
        
        public synchronized void out()
        {
            while(!flag) {
                    try{this.wait();}catch(Exception e){}
            }        
            System.out.println(Thread.currentThread().getName()+"消费者---------"+name);
            flag = false;
            this.notifyAll();
        }
    }
    
    class Producer implements Runnable
    {
          private Resource re;
            Producer(Resource re)
            {
                this.re = re;    
            }
            
            public void run ()
            {
                while(true)
                {
                    re.set("商品");
                }    
            }
    }
    
    class Consumer implements Runnable
    {
          private Resource re;
            Consumer(Resource re)
            {
                this.re = re;    
            }
            
            public void run ()
            {
                while(true)
                {
                    re.out();
                }    
            }
    }    


8.JDK1.5中提供了多线程升级解决方案
    将同步sychronized 替换成现实Lock操作
    将Object中的wait,notify notifyAll替换成了Condition对象
    该对象可以Lock锁,进行获取。
    可以只唤醒对方操作。
    
10.停止线程
            stop方法已经过时。
            如何停止线程呢?
            只有一种,run方法结束。
            开启多线程运行,运行代码通常是循环结构的。
            只要控制住循环,就可以让run方法结束。也就是线程结束。
        特殊情况:
            当线程处于冻结状态。
            就不会读取到标记。那么线程就不会结束。
            
            当没有指定的方法让冻结的线程恢复到运行状态时,这时需要对冻结进行清除。interrupt()
            强制让线程恢复到运行状态中来。
    class StopThreadDemo
    {
        public static void main(String[] args)
        {
          StopThread s = new StopThread();
            Thread t1 = new Thread(s);
            Thread t2 = new Thread(s);
            t1.start();
            t2.start();
            int x = 0;
            while(true)
            {
                    if(x++ == 60)
                    {
                        t1.interrupt();
                        t2.interrupt();
                        break;
                    }
                    System.out.println(Thread.currentThread().getName()+"..main.."+x);
            }
        }
    }
    
    class StopThread implements Runnable
    {
        boolean flag = true;
        public synchronized void run()
        {
    
            while(flag)
            {
                    try {
                        wait();
                    } catch(InterruptedException  e) {
                        flag = false;    
                        System.out.println(Thread.currentThread().getName()+"..exception..");
                    }
                    System.out.println(Thread.currentThread().getName()+"..run..");
            }    
        }    
    }


11. t.join();      该线程抢占cpu,他结束后别人才能运行。
   特点:当A线程执行到了B线程的join方法时,
                 A线程就会等待,B结束后A才会执行。
   join可以临时加入线程执行。


   
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值