多线程知识点:锁

/*
解决多生产多消费的效率问题。
使用了JDK1.5 java.util.concurrent.locks包中的对象。
Lock接口:它的出现比synchronized有更多的操作。
            lock():获取锁。
            unlock():释放锁。

同步代码块或者同步函数的锁操作是隐式的。
JDK1.5 Lock接口,按照面向对象的思想,将锁单独封装成了一个对象。
                 并提供了对锁的显示操作。

Lock接口就是同步的替代。
1,将线程中的同步更换为Lock接口的形式。

替换完运行失败了。因为wait没有了同步区域,没有了所属的同步锁。
同步升级了。其中锁已经不是在任意对象,而是Lock类型的对象。
那么和任意对象绑定的监视器方法,是不是也升级了,有了专门和Lock类型锁的绑定的监视器方法呢?
查阅api。Condition接口替代了Object中的监视器方法。

以前监视器方法封装到每一个对象中。
现在将监视器方法封装到了Condition对象中。
方法名为:await  signal  signalAll 


监视器对象Condition如何和Lock绑定呢?
可以通过Lock接口的newCondition()方法完成。

但是,问题依据,一样唤醒了本方。效率仍旧低!




*/
import java.util.concurrent.locks.*;

//描述资源。
class Res
{
    private String name;
    private int count = 1;
    //创建新Lock。
    private Lock lock = new ReentrantLock();

    //创建和Lock绑定的监视器对象。创建两个。
    //生产者监视器。
    private Condition producer_con = lock.newCondition();
    //消费者监视器
    private Condition consumer_con = lock.newCondition();
    
    //定义标记。
    private boolean flag;
    //提供了给商品赋值的方法。
    public  void set(String name)//
    {
        //获取锁。
        lock.lock();

        try{
            while(flag)//判断标记为true,执行wait。等待。为false。就生产。
                try{producer_con.await();}catch(InterruptedException e){}//t0(等)  t1(等)
            this.name  = name + "--" + count;//面包1  ,面包2 面包3

            count++;//2  3 4
            System.out.println(Thread.currentThread().getName()+"...生产者....."+this.name);//t0  面包1、 t0 面包2 t1 ,面包3
            //生成完毕,将标记改为true。
            flag = true;
            //生产完毕,应该唤醒一个消费者来消费。
            consumer_con.signal();

        }finally{

            //释放锁。
            lock.unlock();
        }
    }

    //提供一个获取商品的方法。
    public void get()//
    {
        lock.lock();
        try{
        while(!flag)
            try{consumer_con.await();}catch(InterruptedException e){}//t2(等)  t3(等)
        System.out.println(Thread.currentThread().getName()+".......消费者....."+this.name);//t2  面包1.

        //将标记改为false。
        flag = false;
        //消费完后,应该唤醒生产者一个。
        producer_con.signal();
        }finally{
            lock.unlock();
        }
    }
}


//生成者。
class Producer implements Runnable
{
    private Res r;
    Producer(Res r)
    {
        this.r = r;
    }
    public void run()
    {
        while(true)
            r.set("面包");
    }
}

//消费者
class Consumer implements Runnable
{
    private Res r;
    Consumer(Res r)
    {
        this.r = r;
    }
    public void run()
    {    
        while(true)
            r.get();
    }
}




class  NewProducerConsumerDemo
{
    public static void main(String[] args) 
    {
        //1,创建资源。
        Res r = new Res();
        //2,创建两个任务。
        Producer pro = new Producer(r);
        Consumer con = new Consumer(r);

        //3,创建线程。
        Thread t0 = new Thread(pro);
        Thread t1 = new Thread(pro);
        Thread t2 = new Thread(con);
        Thread t3 = new Thread(con);

        t0.start();
        t1.start();
        t2.start();
        t3.start();
    }
}

class BoundedBuffer {
   final Lock lock = new ReentrantLock();
   final Condition notFull  = lock.newCondition(); 
   final Condition notEmpty = lock.newCondition(); 

   final Object[] items = new Object[100];
   int putptr, takeptr, count;

   public void put(Object x) throws InterruptedException {
     lock.lock();
     try {
       while (count == items.length) 
         notFull.await();
       items[putptr] = x; 
       if (++putptr == items.length) putptr = 0;
       ++count;
       notEmpty.signal();
     } finally {
       lock.unlock();
     }
   }

   public Object take() throws InterruptedException {
     lock.lock();
     try {
       while (count == 0) 
         notEmpty.await();
       Object x = items[takeptr]; 
       if (++takeptr == items.length) takeptr = 0;
       --count;
       notFull.signal();
       return x;
     } finally {
       lock.unlock();
     }
   } 
 }
wait()和sleep()的区别。

相同:可以让线程处于冻结状态。

不同点:
1,wait()可以指定时间,也可以不指定。
    sleep().必须指定时间。

2,wait();释放cpu资源,释放锁。
    sleep():释放cpu资源,不释放锁。



synchronized(obj)
{

    obj.wait();//t0,t1,t2
    code....;



}
synchronized(obj)
{

    obj.notifyAll();//t3
}

class  
{
    public static void main(String[] args) 
    {
        System.out.println("Hello World!");
    }
}
/*
异常会提示发生在哪个线程上。
异常会结束线程任务,也就是可以结束所在线程。

*/
class Demo implements Runnable
{
    public void run()
    {
        System.out.println(4/0);
    }
}


class ThreadExceptionDemo 
{
    public static void main(String[] args) throws Exception
    {
        new Thread(new Demo()).start();
        Thread.sleep(10);
        int[] arr = new int[3];
        System.out.println(arr[2]);
        System.out.println("over");
    }
}
/*
如何停止线程?

原理:让run方法结束。
    线程任务通常都有循环。因为开启线程就是为了执行需要一些时间的代码。

    只要控制住循环,就可以结束run方法,就可以停止线程。

    控制循环弄个标记即可。定义变量


*/

class StopThread implements Runnable
{
    private boolean flag = true;

    public synchronized void run()
    {
        while(flag)
        {
            try
            {
                wait();//t1 t2
            }
            catch (InterruptedException e)
            {
                System.out.println(Thread.currentThread().getName()+"............"+e.toString());
                flag = false;
            }
            System.out.println(Thread.currentThread().getName()+"....hello");
        }
        
    }
    public void changeFlag()
    {
        flag = false;
    }
}


class StopThreadDemo 
{
    public static void main(String[] args) 
    {
        StopThread st = new StopThread();
        Thread t1 = new Thread(st);
        Thread t2 = new Thread(st);
        t1.start();
        t2.setDaemon(true);//将t2标记为后台线程。
        t2.start();
        for(int x=1; x<=50; x++)
        {

            if(x==40){
                t1.interrupt();//将t1中断。
//                t2.interrupt();//将t2中断。
//                st.changeFlag();
            }
            System.out.println("main...."+x);
        }

        System.out.println("over");
    }
}
class Demo implements Runnable
{

    public void run()
    {
        for(int x=1; x<=40; x++)
        {
            System.out.println(Thread.currentThread().toString()+"......"+x);
            Thread.yield();
        }
    }
}


class JoinDemo 
{
    public static void main(String[] args)throws InterruptedException 
    {
        Demo d = new Demo();
        Thread t1 = new Thread(d);
        Thread t2 = new Thread(d);
        t1.start();
        t2.start();
//        t1.join();//等待该线程终止。

        t1.setPriority(Thread.MAX_PRIORITY);
        for(int x=1; x<=40; x++)
        {
            System.out.println(Thread.currentThread().toString()+"...."+x);
        }

    }
}
原文地址:https://www.cnblogs.com/vijay/p/3511267.html