• Java多线程的实现方式二


    Lock(锁)
     从JDK 5.0开始,Java提供了更强大的线程同步机制——通过显式定义同步锁对象来实现同步。同步锁使用Lock对象充当。
     java.util.concurrent.locks.Lock接口是控制多个线程对共享资源进行访问的工具。锁提供了对共享资源的独占访问,每次只能有一个线程对Lock对象加锁,线程开始访问共享资源之前应先获得Lock对象。
     ReentrantLock 类实现了 Lock ,它拥有与 synchronized 相同的并发性和
    内存语义,在实现线程安全的控制中,比较常用的是ReentrantLock,可以显式加锁、释放锁
    实现
    import java.util.concurrent.locks.ReentrantLock;
    
    class Window implements Runnable{
        private int tic = 10;
        //实例化lock
        private ReentrantLock lock = new ReentrantLock();
        @Override
        public void run() {
            while (true){
                try {
                    //调用lock锁定方法
                    lock.lock();
                    if (tic>0){
                        try {
                            Thread.sleep(100);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        System.out.println(Thread.currentThread().getName()+":飘号"+":"+tic);
                        tic--;
                    }else {
                        break;
                    }
                }finally {
                    //3.调用解锁方法
                    lock.unlock();
                }
    
            }
    
        }
    }
    public class LookTest {
        public static void main(String[] args) {
            Window w = new Window();
            Thread t1= new Thread(w);
            Thread t2= new Thread(w);
            Thread t3= new Thread(w);
            t1.start();
            t2.start();
            t3.start();
    
        }
    }
    
    
    
    测试结果
    Thread-0:飘号:10
    Thread-0:飘号:9
    Thread-0:飘号:8
    Thread-0:飘号:7
    Thread-1:飘号:6
    Thread-1:飘号:5
    Thread-1:飘号:4
    Thread-1:飘号:3
    Thread-2:飘号:2
    Thread-2:飘号:1
    
    Process finished with exit code 0
    

      synchronized 与lock的

    形同点解决线程安全问题

    不同点:synchronized机制在执行完相应的代码块以后,自动的释放同步监视器

                    lock需要手动的启动同步,同时结束也需要手动释放监视器

    线程通信问题

         

    /**
     * 线程通信的例子
     * wait():一旦线程执行此方法进入阻塞状态,并且释放锁
     * notify(): 一旦执行此方法,就会和唤醒wait的线程,如果多个线程wait,就唤醒优先及高的线程
     * notifyAll():一旦执行此方法,就会唤醒所以被wait的线程
     *说明:1.wait(),notify(),notifyAll()三个方法必须使用在同步代码块,或同步方法中。
     * 2.wait(),notify(),notifyAll()三个方法的调用者必须是同步代码块或同步方法中的同步监视器;
     *   否则java.lang.IllegalMonitorStateException
     *
     */
    class Number implements Runnable{
        private int number=1;
        private Object obj = new Object();
    
        @Override
        public void run() {
            while (true){
                synchronized (obj) {
                    obj.notify();
                    if (number<=10){
                        System.out.println(Thread.currentThread().getName()+":"+number);
                        number++;
                        try {
                            //使得调用此wait()方法的线程进入阻塞状态,并会释放锁
                            obj.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }else {
                        break;
                    }
                }
            }
        }
    }
    public class CommunicationTest {
        public static void main(String[] args) {
            Number n1 = new Number();
    
            Thread thread1 = new Thread(n1);
            Thread thread2 = new Thread(n1);
            thread1.setName("线程1");
            thread2.setName("线程2");
            thread1.start();
            thread2.start();
          // System.out.println();
        }
    }
    测试结果
    线程1:1
    线程2:2
    线程1:3
    线程2:4
    线程1:5
    线程2:6
    线程1:7
    线程2:8
    线程1:9
    线程2:10
    
    Process finished with exit code 0
    

      sleep()和wait()方法

    相同点:线程执行到它们的时候进入阻塞状态

    不同点:两个方法声明的位置不同;Thread类中声明seelp(),Object中声明的wait()

                 调用的范围不一样,seelp()可以在任何需要的场景下调用,wait()必须使用在同步代码块

                 是否释放同步监视器的问题:如果两个方法都使用在同步代码块或者同步方法中,seelp()方法不会释放锁,而wait()会释放锁

       线程通信应用

    class Clerk{
        private int productCount =0;
    
        public void producProuluct() {
            if(productCount<20){
                productCount++;
                System.out.println(Thread.currentThread().getName()+":开始生产"+productCount);
            }
        }
    //消费
        public void consumeProduct(){
            if (productCount>0){
    
              System.out.println(Thread.currentThread().getName()+":"+productCount);
                productCount--;
          }
        }
    }
    class Producer extends Thread{//生产者
        private Clerk clerk;
    
        public Producer(Clerk clerk){
            this.clerk= clerk;
        }
    
        @Override
        public void run() {
            System.out.println(getName()+":生成");
            while (true){
                clerk.producProuluct();
            }
        }
    }
    class  Consumer extends Thread{
        private Clerk clerk;
        public Consumer(Clerk clerk){
            this.clerk= clerk;
        }
    
        @Override
        public void run() {
            System.out.println(getName()+":消费");
            while (true){
                clerk.consumeProduct();
            }
    
        }
    }
    public class ProductTest {
        public static void main(String[] args) {
            Clerk clerk = new Clerk();
            Producer p1 = new Producer(clerk);
            p1.setName("生产者1");
            Consumer consumer = new Consumer(clerk);
            consumer.setName("消费者");
            p1.start();
            consumer.start();
        }
    
    }
    
    
    测试结果
    生产者1:开始生产3
    生产者1:开始生产1
    生产者1:开始生产2
    生产者1:开始生产3
    生产者1:开始生产4
    生产者1:开始生产5
    生产者1:开始生产6
    生产者1:开始生产7
    生产者1:开始生产8
    消费者:1
    消费者:8
    消费者:7
    消费者:6
    消费者:5
    消费者:4
    生产者1:开始生产9
    生产者1:开始生产4
    生产者1:开始生产5
    生产者1:开始生产6
    生产者1:开始生产7
    生产者1:开始生产8
    生产者1:开始生产9
    生产者1:开始生产10
    生产者1:开始生产11
    生产者1:开始生产12
    生产者1:开始生产13
    消费者:3
    消费者:13
    生产者1:开始生产14
    生产者1:开始生产14
    生产者1:开始生产15
    生产者1:开始生产16
    生产者1:开始生产16
    生产者1:开始生产17
    生产者1:开始生产18
    生产者1:开始生产19
    生产者1:开始生产20
    消费者:15
    消费者:20
    消费者:19
    消费者:18
    消费者:17
    

      

     

    草都可以从石头缝隙中长出来更可况你呢
  • 相关阅读:
    手游营销的10个靠谱方向
    创业三个月总结---记录这三个月的酸甜苦辣咸!!!
    创业三个月总结---记录这三个月的酸甜苦辣咸!!!
    Notepad++ 删除空白行的方法
    Notepad++ 删除空白行的方法
    几种常见容器比较和分析 hashmap, map, vector, list ...hash table
    hdu 3371
    hdu 1879
    hdu 1875
    hdu 1863
  • 原文地址:https://www.cnblogs.com/rdchenxi/p/14674651.html
Copyright © 2020-2023  润新知