【Java】多线程-知识点总结

一、创建线程方式

  • 继承Thread类创建线程类
  • 通过Runnable接口创建线程类
  • 通过Callable和Future创建线程

创建线程三种方式详细

二、关于start、Run线程区别

线程的启动方式只能通过start这种方式启动才能真正的实现多线程的效果,如果是手动调用run方法和普通方法调用没有区别

三、流程图

在这里插入图片描述

四、sleep() 、wait() 等方法

1.sleep()方法

  • 在指定时间内让当前正在执行的线程暂停执行,但不会释放“锁标志”。不推荐使用。

  • sleep()使当前线程进入阻塞状态,在指定时间内不会执行。

  • (休眠)是线程类(Thread)的静态方法,调用此方法让当前线程暂停执行指定的时间,将执行机会(CPU)让给其他线程,但是对象的锁依然保持,因此休眠时间结束后会自动恢复

2.wait()方法

  • 在其他线程调用对象的notify或notifyAll方法前,导致当前线程等待。线程会释放掉它所占有的“锁标志”,从而使别的线程有机会抢占该锁。

  • 当前线程必须拥有当前对象锁。如果当前线程不是此锁的拥有者,会抛出IllegalMonitorStateException异常。

  • 唤醒当前对象锁的等待线程使用notify或notifyAll方法,也必须拥有相同的对象锁,否则也会抛出IllegalMonitorStateException异常。

  • waite()和notify()必须在synchronized函数或synchronized block中进行调用。如果在non-synchronized函数或non-synchronized block中进行调用,虽然能编译通过,但在运行时会发生IllegalMonitorStateException的异常。

  • 是Object类的方法,调用对象的wait()方法导致当前线程放弃对象的锁(线程暂停执行),进入对象的等待池(wait pool),只有调用对象的notify()方法(或notifyAll()方法)时才能唤醒等待池中的线程进入等锁池(lock pool),如果线程重新获得对象的锁就可以进入就绪状态。

3.yield方法

  • 暂停当前正在执行的线程对象。

  • yield()只是使当前线程重新回到可执行状态,所以执行yield()的线程有可能在进入到可执行状态后马上又被执行。

  • yield()只能使同优先级或更高优先级的线程有执行的机会。

4.join方法

  • join()等待该线程终止。
  • 等待调用join方法的线程结束,再继续执行。如:t.join();//主要用于等待t线程运行结束,若无此句,main则会执行完毕,导致结果不可预测

五、用户线程(user-level threads)

用户线程(user-level threads) 指不需要内核支持而在用户程序中实现的线程,其不依赖于操作系统核心,应用进程利用线程库提供创建、同步、调度和管理线程的函数来控制用户线程。

六、ThreadLocal

  • ThreadLocal是采用哈希表的方式来为每个线程都提供一个变量的副本

  • ThreadLocal保证各个线程间数据安全,每个线程的数据不会被另外线程访问和破坏

七、InterruptedException抛出

  • java.lang.Object 类的 wait 方法

  • java.lang.Thread 类的 sleep 方法

  • java.lang.Thread 类的 join 方法

八、volatile

一旦一个共享变量(类的成员变量、类的静态成员变量)被volatile修饰之后,那么就具备了两层语义:

1)保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变量的值,这新值对其他线程来说是立即可见的。

2)禁止进行指令重排序。

volatile只提供了保证访问该变量时,每次都是从内存中读取最新值,并不会使用寄存器缓存该值——每次都会从内存中读取。

而对该变量的修改,volatile并不提供原子性的保证。

由于及时更新,很可能导致另一线程访问最新变量值,无法跳出循环的情况

多线程下计数器必须使用锁保护。

九、线程共享

方法区和堆内存是线程共享的。

程序计数器、虚拟机栈是线程隔离的。
在这里插入图片描述

发布了130 篇原创文章 · 获赞 8 · 访问量 2818

猜你喜欢

转载自blog.csdn.net/ange2000561/article/details/105094666