zoukankan      html  css  js  c++  java
  • jdk线程常见面试题

    请编写一个多线程程序,实现两个线程,其中一个线程完成对某个对象int成员变量的增加操作,即每次加1,另一个线程完成对该对象成员变量的减操作,即每次减1,同时要保证该变量的值不会小于0,不会大于1,该变量的初始值为0。

    class Sample {
    
        private int number;
    
        public synchronized void increase() {
            while (0 != number) {
                try {
                    this.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            number++;
            System.out.println(number);
            this.notifyAll();
        }
    
        public synchronized void decrease() {
            while (0 == number) {
                try {
                    this.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            number--;
            System.out.println(number);
            this.notifyAll();
    
        }
    }
    
    class IncreaseThread implements Runnable {
    
        private Sample sample;
    
        public IncreaseThread(Sample sample) {
            this.sample = sample;
        }
    
        @Override
        public void run() {
            for (int i = 0; i < 20; i++) {
                try {
                    Thread.sleep((long)(Math.random() * 1000));
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                sample.increase();
            }
        }
    }
    
    class DecreaseThread implements Runnable {
    
        private Sample sample;
    
        public DecreaseThread(Sample sample) {
            this.sample = sample;
        }
    
        @Override
        public void run() {
            for (int i = 0; i < 20; i++) {
                try {
                    Thread.sleep((long)(Math.random() * 1000));
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                sample.decrease();
            }
        }
    }
    
    public class MainTest {
        public static void main(String[] args) {
            Sample sample = new Sample();
            Runnable runnable1 = new IncreaseThread(sample);
            Runnable runnable2 = new DecreaseThread(sample);
    
            Thread thread1 = new Thread(runnable1);
            Thread thread2 = new Thread(runnable2);
    
            thread1.start();
            thread2.start();
        }
    } 

    关于wait(),notify(),notifyAll()以及sleep()方法的关系

    1)如果一个线程调用了某个对象的wait方法,那么该线程首先必须要拥有对象的锁(synchronized),换句话说,该wait方法必须出现在synchronized中;

    2)如果一个线程调用了某个对象的wait方法,那么该线程就会释放该对象的锁;

    3)在java对象中,有两种池(锁池和等待池);

    4)如果一个线程调用了某个对象的wait方法,那么线程进入该对象的等待池(释放锁),如果未来某一时刻另一个线程调用了相同对象的notify/notifyAll方法,那么在该等待池中等待的线程就会起来进入该对象的锁池中,去等待获得该对象的锁,如果获得锁成功后,那么该线程将继续沿着wait方法之后的路径去执行;

    5)Thread.sleep(long),如果一个线程调用了sleep方法睡眠,那么在睡眠的同时,不会丢失对象的锁的所有权;

    6)wait、notify、notifyAll方法都是定义在Object类中的,而且是final的,因此会被所有的Java类所继承并且无法重写。这两个方法要求在调用时线程应该已经获得了对象的锁。这三个方法必须由同步监视对象/锁来调用,锁可以是任意的对象,任意的对象调用的方式一定定义在Object中;

    7)notify方法是去等待池中随机的唤醒一个正在等待的线程,而notifyAll方法是唤醒所有等待池中的线程;

    8)wait有个重载的方法public final void wait(long timeout),表示在指定的时候过了以后,线程自动进入等待池等待被调用;当指定的时间没有到的时候可以通过notify/notifyAll的方法唤醒;

    9)wait():让当前线程放弃监视器进入等待,直到其他线程调用同一个监视器并调用notify()或notifyAll()为止;
    notify():唤醒在同一对象监听器中调用wait方法的第一个线程;
    notifyAll():唤醒在同一对象监听器中调用wait方法的所有线程。

    10) wait可以指定时间也可以不指定时间;sleep必须指定时间;在同步中时,对CPU的执行权和锁的处理不同:wait释放执行权,释放锁;sleep释放执行权,不释放锁;

    11) synchronized修饰的方法,因为该类的默认实例(this)是同步监视器,所有可以在同步方法中直接调用这三个方法;synchronized修饰的同步代码块,同步监视器是括号里的对象,所以必须使用该对象调用这三个方法;

    12) 使用Lock对象来保证同步时,系统中不存在隐式的同步监视对象,那么就不能使用这三个方法了,那该怎么办呢?此时,Lock代替了同步方法/同步代码块,将同步的隐式锁变成显示锁操作,可以为一个锁加上多组监视器。Condition代替了同步监视器的功能。Condition对象通过Lock对象的newCondition()方法创建;
    里面方法包括: await(): 等价于同步监听器的wait()方法;signal(): 等价于同步监听器的notify()方法; signalAll(): 等价于同步监听器的notifyAll()方法;
    以前一个锁上只能有一组监视器方法。现在,一个Lock锁上可以多组监视器方法对象。可以实现一组负责生产者,一组负责消费者。

    synchronized关键字的作用
    1)在某个对象的所有synchronized方法中,在某一个时刻,只能有唯一的一个线程去访问这些synchronized方法;

    2)如果一个方法是synchronized方法,那么该synchronized关键字给当前对象上锁(即this);

    3)如果一个synchronized方法是static的,那么该synchronized关键字表示的是给当前对象所对应的Class对象上锁(每个类,不管生成多少对象,其对应的Class只有一个)。

  • 相关阅读:
    CSS浮动(float、clear)通俗讲解
    JAVA 类的加载
    数据库操作 delete和truncate的区别
    正则表达式 匹配相同数字
    Oracle EBS OM 取消订单
    Oracle EBS OM 取消订单行
    Oracle EBS OM 已存在的OM订单增加物料
    Oracle EBS OM 创建订单
    Oracle EBS INV 创建物料搬运单头
    Oracle EBS INV 创建物料搬运单
  • 原文地址:https://www.cnblogs.com/luogankun/p/3991383.html
Copyright © 2011-2022 走看看