• 多线程技术点


    1.Thread.currentThread()

    返回代码段正在被哪个线程调用

    注意currentThread()和this的差异

    2.isAlive()

    Thread.isAlive()、this.isAlive()

    判断当前的线程是否处于活动状态。

    3.sleep()

    Thread.sleep()

    4.getId()

    5.Thread.interrupted():测试当前线程是否已经中断,当前线程是指运行this.interrupted()方法的线程。具有清除状态的功能

    6.this.isInterrupted():测试线程是否已经中断

    7.中断main线程:Thread.currentThread().interrupt();

    8.线程中有for循环,如果该线程被停止,但for语句下面还有语句,还是会继续运行的。可以使用中断法,停止循环

    for(int i=0;i<5000;i++){
        if(this.interrupted()){
            System.out.println("been stopped!");
            throw new InterruptedException();
        }
        System.out.print("i="+(i+1));
    }
    System.out.println("under for");

    9.线程在沉睡中停止会出现InterruptedException异常

    10.方法stop()已经被作废,因为如果强制让线程停止,则有可能使一些清理性的工作得不到完成。

    另外一个情况就是对锁定的对象进行了“解锁”,导致数据得不到同步的处理,出现数据不一致的问题。

    11.使用return停止线程

    while(true){
        if(this.isInterrupted()){
            System.out.println("stop!");
            return ;
        }
        System.out.println("after while");
    }

    12.suspend(),resume()

    在使用suspend与resume方法时,如果使用不当,极易造成公共的同步对象的独占,使得其他

    13.yield方法

    yield()方法的作用是放弃当前的CPU资源,将它让给其他的任务去占用CPU执行时间。但放弃的时间不确定,有可能刚刚放弃,马上又获得CPU时间片

    14.守护线程Daemon

    当进程中不存在非守护线程了,则守护线程自动销毁

    15.在两个线程访问同一个对象中的同步方法时一定是线程安全的。

    16.Synchronized锁重入

    关键字Synchronized拥有锁重入的功能,也就是在使用Synchronized时,当一个线程得到一个对象锁后,再次请求此对象锁时是可以再次得到该对象的锁的。

    17.出现异常,锁自动释放

    18.同步不具有继承性,所以子类必须在继承的方法加上Synchronized关键字

    19.使用synchronized(非 this 对象 x)同步代码块格式进行同步操作时,对象监视器必须是同一个对象。

    20.关键字Synchronized还可以应用在static静态方法上,如果这样写,那是对当前的*.java文件对应的Class类进行持锁,Class锁可以对类的所有对象实例起作用

    21.只要对象不变,即使对象的属性被改变,运行的结果还是同步。

    22.线程安全包含原子性和可见性两个方面,Java的同步机制都是围绕这两个方面来确保线程安全的

    23.等待/通知机制

    在调用wait()之前,线程必须获得该对象的对象级别锁,即只能在同步方法或同步块中调用wait()方法。在执行wait()方法后,当前线程释放锁。

    在从wait()返回前,线程与其他线程竞争重新获得锁

    方法notify()也要在同步方法或同步块中,调用,即在调用前,线程也必须获得该对象的对象级别锁。

    在执行notify()方法后,当前线程不会马上释放该对象锁,呈wait状态的线程也并不能马上获取该对象锁,要等到执行notify()方法的线程将程序执行完,也就是退出synchronized代码块后,当前线程才会释放锁。

    每个锁对象都有两个队列,一个是就绪队列,一个是阻塞队列。就绪队列存储了将要获得锁的线程,阻塞队列存储了被阻塞的线程。一个线程被唤醒后,才会进入就绪队列,等待CPU调度;反之,一个线程被wait后,就会进入阻塞队列,等待下一次被唤醒。

    当方法wait()被执行后,锁被自动释放,但执行完notify()方法,锁却不自动释放。

    24.当线程呈wait()状态时,调用线程对象的interrupt()方法会出现InterruptedException异常。

    25.带一个参数的wait(long)方法的功能是等待某一时间内是否有线程对锁进行唤醒,如果超过这个时间则自动唤醒。

    26.处理生产者,消费者的关键点在于,使用while代替if语句对可能变化的条件进行判断,然后使用notifyAll()方法代替notify()方法,notifyAll()不光通知同类线程,也通知异类线程。

    27.在很多情况下,主线程创建并启动子线程,如果子线程中要进行大量的耗时运算,主线程往往将早于子线程结束之前结束。

    这时,如果主线程想等待子线程执行完成之后再结束,比如子线程处理一个数据,主线程要取得这个数据中的值,就要用到join()方法了,方法join()的作用是等待线程对象销毁

    28.在join过程中,如果当前线程对象被中断,则当前线程出现异常。

    29.join(long)可以设定等待的时间

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

    方法join(long)的功能在内部是使用wait(long)方法来实现的,所以join(long)方法具有释放锁的特点。

    Thread.sleep(long)方法不释放锁。

    31.ThreadLocal可以实现每一个线程都有自己的共享变量。

    ThreadLocal类接口很简单,只有4个方法,我们先来了解一下:

    • void set(Object value)设置当前线程的线程局部变量的值。
    • public Object get()该方法返回当前线程所对应的线程局部变量。
    • public void remove()将当前线程局部变量的值删除,目的是为了减少内存的占用,该方法是JDK 5.0新增的方法。需要指出的是,当线程结束后,对应该线程的局部变量将自动被垃圾回收,所以显式调用该方法清除线程的局部变量并不是必须的操作,但它可以加快内存回收的速度。
    • protected Object initialValue()返回该线程局部变量的初始值,该方法是一个protected的方法,显然是为了让子类覆盖而设计的。这个方法是一个延迟调用方法,在线程第1次调用get()或set(Object)时才执行,并且仅执行1次。ThreadLocal中的缺省实现直接返回一个null。

    32.ReentrantLock——lock(),unlock(),newCondition()

    33. Condition——await(),signal()

    34.公平锁与非公平锁

    公平锁表示线程获取锁的顺序是按照线程加锁的顺序来分配的,而非公平锁就是一种获取锁的抢占机制,是随机获得锁的。

    创建公平锁:ReentrantLock lock = new ReentrantLock(true)

    35.getHoldCount()——查询当前线程保持此锁定的个数(获取锁后再调用受相同锁控制的方法)

    36.getQueueLength()——返回正等待获取此锁定的线程估计数

    37.getWaitQueueLength(Condition condition)——返回等待与此锁定相关的给定条件Condition的线程估计数

    38.boolean hasQueuedThread(Thread thread)——查询指定的线程是否在等待获取此锁定,boolean hasQueuedThreads()

    39.boolean hasWaiters(Condition condition)——查询是否有线程正在等待与此锁定有关的condition条件

    40.boolean isHeldByCurrentThread()——查询当前线程是否保持此锁定

    41.boolean isLocked()——查询此锁定是否由任意线程保持

    42.lockInterruptibly()——如果当前线程未被中断,则获取锁定,如果已经被中断则出现异常

      当通过lockInterruptibly()方法获取某个锁时,如果不能获取到,只有进行等待的情况下,是可以响应中断的。

      而用synchronized修饰的话,当一个线程处于等待某个锁的状态,是无法被中断的,只有一直等待下去。

    43.tryLock()——仅在调用时锁定未被另一个线程保持的情况下,才获取该锁定。

    44.condition.awaitUninterruptibly()——不能被中断

    45.condition.awaitUntil(time)——如果没有其他线程唤醒,到达指定时间time后,自动进行唤醒。

    46.ReentrantReadWriteLock——共享锁和排他锁。

    lock.readLock().lock(),lock.writeLock().lock()

    47.定时器

    Timer类的主要作用就是设置计划任务,但封装任务的类却是TimerTask类。

    schedule(TimerTask task, Date time)——在指定的日期执行一次某任务

    创建一个Timer就是启动一个新的线程,那么这个新启动的线程并不是守护线程,而是一直在运行

        public static void main(String[] args) throws InterruptedException {
            // TODO Auto-generated method stub
            Calendar cal = Calendar.getInstance();
            cal.add(Calendar.SECOND, 3);
            
            MyTask task = new MyTask();
            Timer timer=new Timer(true);
            timer.schedule(task, cal.getTime());
            Thread.sleep(5000);
        }

    如果执行任务的时间早于当前时间,则立即执行task任务

    48.Timer中允许有多个TimerTask任务及延时的测试,其中TimerTask是以队列的方式一个一个被顺序地执行

    49.TimerTask类的cancel()方法:作用是将自身从任务队列中进行清除

    50.Timer类的cancel()方法:将任务队列中全部的任务进行清空。

    51.schedule和scheduleAtFixedRate主要的区别只在于有没有追赶特性

    对于延时任务,两者下一次任务的执行时间都是以上一次任务“结束”时的时间作为参考来计算,并没有运行效果上的区别,

  • 相关阅读:
    远程服务器Xshell的使用 -- 重启服务器操作 和 linux的常用命令
    Spring Boot 服务端开发项目目录结构
    font-weight字体重量和font-family字体类型中的粗细度的对应关系
    iframe的使用
    js 多个箭头函数的使用
    js 获取本地上传的文件(图片和视频)的宽高和大小
    react-navigation Modal弹出层中的StackNavigator导航如何和物理返回匹配?
    IntelliJ IDEA 2019.3的安装和激活
    android EditText 的聚焦和失焦,输入框的监听
    Android 系统架构 和 各个版本代号介绍
  • 原文地址:https://www.cnblogs.com/lvjygogo/p/8684324.html
Copyright © 2020-2023  润新知