多线程技术点

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主要的区别只在于有没有追赶特性

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

原文地址:https://www.cnblogs.com/lvjygogo/p/8684324.html