• 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只有一个)。

  • 相关阅读:
    robot framework 实例:126邮箱登录
    python帮助文档查看
    robot framework 测试库安装
    robot framework 变量与常量
    robot framework连接mysql数据库
    、搭建Android开发环境
    基于Eclipse的Android开发环境搭建
    MySQLzip压缩文件格式安装教程
    tomcat版本号的修改
    java时间格式
  • 原文地址:https://www.cnblogs.com/luogankun/p/3991383.html
Copyright © 2020-2023  润新知