• Java多线程技术-wait/notify/join


    wait/notify的作用

    wait()方法的作用是使当前执行代码的线程进行等待,wait()是Object类的方法,用来将当前线程置入预执行队列中,并且在wait()所在的代码处停止执行,直到接到通知或被中断为止。wait()调用前,必须获得该对象的对象级锁,即只能在同步方法或者同步代码块中调用wait()方法,否则会抛出IllegalMonitorStateException。当wait()执行后,当前线程释放锁

    notify()方法的作用是用来通知那些可能等待该对象的对象锁的其他线程,如果有多个线程等待,则随机挑选出一个wait状态的线程,对其发出通知,并使它等待获取该对象的对象锁。notify()调用前,必须获得该对象的对象级锁,即只能在同步方法或者同步代码块中调用notify()方法,否则会抛出IllegalMonitorStateException。当notify()方法执行后,不会马上释放该对象的锁,呈wait状态的线程也并不能马上获得该对象锁,要等到执行notify()的线程将程序执行完,也就是退出synchronized代码块后,当前线程才会释放锁。

    notifyAll()方法和notify()作用基本是一样的,一个是唤醒全部的wait线程,一个是唤醒其中一个wait线程。

    经典案例生产者和消费者

    public class MyStack {
        private List<String> list = new ArrayList<>();
    
        public synchronized void push() {
            try {
                while (list.size() == 1) {
                    System.out.println("push:"+Thread.currentThread().getName()+"呈wait状态");
                    this.wait();
                }
                list.add("anyString=" + Math.random());
                this.notifyAll();
                System.out.println("push=" + list.size());
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        
        public synchronized String pop(){
            String returnValue = "";
            try {
                while(list.size() == 0){
                    System.out.println("pop:"+Thread.currentThread().getName()+"呈wait状态");
                    this.wait();
                }
                returnValue = list.get(0);
                list.remove(0);
                this.notifyAll();
                System.out.println("pop="+list.size());
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            return returnValue;
        }
    }
    
    public class Product {
        private MyStack myStack;
        public Product(MyStack myStack) {
            this.myStack = myStack;
        }
        
        public void pushService(){
            myStack.push();
        }
    }
    
    public class Customer {
        private MyStack myStack;
        public Customer(MyStack myStack) {
            this.myStack = myStack;
        }
        
        public void popService(){
            myStack.pop();
        }
    }
    
    public class ThreadCustomer extends Thread {
    
        private Customer customer;
    
        public ThreadCustomer(Customer customer) {
            this.customer = customer;
        }
    
        @Override
        public void run() {
            while(true){
                customer.popService();
            }
        }
    }
    
    public class ThreadProduct extends Thread {
    
        private Product product;
    
        public ThreadProduct(Product product) {
            this.product = product;
        }
    
        @Override
        public void run() {
            while(true){
                product.pushService();
            }
        }
    }
    
    public class Test {
        public static void main(String[] args) throws InterruptedException {
            
            MyStack myStack = new MyStack();
            Product p = new Product(myStack);
            Customer c = new Customer(myStack);
            
            ThreadProduct pThread = new ThreadProduct(p);
            ThreadCustomer cThread = new ThreadCustomer(c);
            pThread.start();
            cThread.start();
                    
        }
    }
    View Code

    join的作用

    join()是Thread类的一个方法,它的作用是使所属的线程x对象正常的执行run方法中的任务,而使当前线程z进行无限期的阻塞,等待线程x销毁后再继续执行线程z后面的代码。

    public class MyThread extends Thread{
        @Override
        public void run() {
            try {
                System.out.println(System.currentTimeMillis());
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
    
    public class Test {
        public static void main(String[] args) throws InterruptedException {
            MyThread myThread = new MyThread();
            myThread.start();
            myThread.join();
            System.out.println("在myThread执行完后输出:" + System.currentTimeMillis());
        }
    }
    View Code

    测试结果:

    1516170164683
    在myThread执行完后输出:1516170167686

    join和synchronized的区别

    从上面的例子可以看出,join方法具有线程排队运行的作用,有些类是同步的运行效果。join和synchronized的区别是:join在内部使用wait()方法进行等待,而synchronized是使用“对象监视器”原理做为同步

    join(long)和sleep(long)的区别

    由于join的内部是使用wait来实现的,所以它具有释放锁的特点,而sleep没有这一特点。

    源码如下:

     public final synchronized void join(long millis)
        throws InterruptedException {
            long base = System.currentTimeMillis();
            long now = 0;
    
            if (millis < 0) {
                throw new IllegalArgumentException("timeout value is negative");
            }
    
            if (millis == 0) {
                while (isAlive()) {
                    wait(0);
                }
            } else {
                while (isAlive()) {
                    long delay = millis - now;
                    if (delay <= 0) {
                        break;
                    }
                    wait(delay);
                    now = System.currentTimeMillis() - base;
                }
            }
        }
  • 相关阅读:
    ML-线性回归
    ML-决策树
    numpy常用知识点备忘(2)
    numpy常用知识点备忘
    ML-朴素贝叶斯算法
    Git常用命令备忘
    机器学习-决策树算法
    机器学习-线性模型(线性回归与逻辑回归)
    深入JVM内核(四)垃圾回收器与GC参数
    深入JVM内核(三)对象存活判定算法与垃圾收集算法
  • 原文地址:https://www.cnblogs.com/lostyears/p/8301626.html
Copyright © 2020-2023  润新知