Java多线程学习笔记

时间:2023-02-25 12:01:23

一、基本概念

1、并发与并行:

   1)并发:多个任务交替执行。

   2)并行:多个任务同时执行。如果系统只有一个CPU,那真实环境中不可能是真实并行,因为一个CPU一次只能执行一个指令。多核CPU有可能出现并行。

2、临界区:
     一种公共资源或共享数据,每一次只能有一个线程使用它。一旦临界区资源被占用,其他线程要想使用这个资源,就必须等待。

3、阻塞(Blocking)和 非阻塞(Non-Blocking):

     阻塞:用来形容多线程间的相互影响。一个线程占用了临界区,其他需要使用这个临界区的线程就必须等待,等待会导致线程挂起,这种情况就是阻塞。

     非阻塞:没有一个线程可以防碍其它线程执行。

4、死锁(DeadLock)、饥饿(Starvation)和活锁(LiveLock):

    死锁: 各线程彼此阻塞。

    饥饿:某个或多个线程由于某种原因(线程优先级太低,或某个线程一直占用资源)无法获得需要的资源,导致一直无法执行。

   活锁:两个线程相互谦让资源,导致没有一个线程可以同时拿到所有资源而正常执行。


5、并发级别:

    根据控制并发的策略,可以发并发级别分为: 阻塞、无饥饿、无障碍、无锁、无等待。   

6、多线程的原子性、可见性、有序性:

    a、 原子性( Atomicity ):指一个操作是不可中断的。即使是在多个线程一起执行的时候,一个操作一旦开始,就不会被其他线程干扰。

           如: 对于32位系统,Long (64位)型数据的读写不是原子性的,

     b、可见性:当一个线程修改了某一个共享变量的值,其他线程是否能够立即知道这个修改。

           如: 多核CPU中,CPU1 将变量 t 缓存在Cache或寄存器, 如果CPU2上的某线程修改了t 的值,则CPU1 不会知道,这就是可见性的问题。

           可见性问题有多种情况: 缓存优化,硬件优化,指令重排,编辑器优化。

     c、有序性:指令重排后,代码执行顺序会变化。


7、线程中断的三种方法:

1)  Thread.interrupt();  // 中断线程

实例方法,通知目标线程中断,即设置中断标志位。中断标志位表示当前线程已经被中断了。

2)  Thread.isInterrupted();  // 判断是否被中断

实例方法,判断当前线程是否有被中断(通过检查中断标志位)。


3) Thread.interrupted();  // 判断是否被中断,并清除当前中断状态。

也用来判断当前线程的中断状态,但同时会清除当前线程的中断标识位状态。


8、Thread.sleep()方法:

  当线程在 sleep()休眠时,如果被中断,则会抛出InterruptException中断异常

该异常不是运行时异常,程序必须捕获并处理它。

9、Object.wait()  方法:

当在一个对象实例上调用 wait()方法后,当前线程就会在这个对象上等待,直到其它线程调用了obj.notify()方法为止。

 obj对象成为多个线程之间的通信手段。

Object.wait()方法必须包含在对应的 synchronized语句中。

执行前需要获得目标对象的监视器 - 用synchronized 语句

wait() 和 sleep()方法的区别:
1)、相同点: 都可以让线程等待,

2)、不同点: wati 可以被唤醒,会释放目标对象的锁,slee()方法不会释放任何资源。


10、Object.notify()方法:随机唤醒(不公平)等待的线程。

         Object.notifyAll()方法:唤醒全部等待队列中的线程。

执行前需要获得目标对象的监视器


11、suspend( 挂起)和 resume (继续执行)线程:

这是两个相反的操作,已经不建议使用。

因为: suspend()在挂起线程时,不释放任何的锁资源,直至对应的线程执行了resume()操作。

但如果 resume()操作先与 suspend()执行,则被挂起的线程在很难有机会被继续执行。

严重时它占用的锁不被释放,会导致整个系统工作不正常。


12、Join (等待线程结束) 和 yield ( 谦让 )  方法:

 Join 方法有两个:

a、 public final void join(): 无限等待,一直阻塞当前线程,直到目标线程执行完毕。

b、 public final synchronized void join( long millis ):给定一个最大等待时间,如超过
等待时间目标线程还在执行,
当前线程会不再等待而继续往下执行。

join()的核心代码是 wait(0);

注:不要在应用程序中,在Thread对象实例上使用类似 wait()或 notify()等方法,
因为这很可能会影响系统API的工作
或者被系统API所影响(为什么? 没有理解)


yield()方法定义: public static native void yield();

静态方法,一旦执行,它会使当前线程让出CPU。但后续还会进行CPU资源的争夺。

如果一个线程不太重要或者优先级低,可以在适当的时候调用 Thread.yield().


13、Java内存模型:原子性、有序性、可见性。


14、volatile: 当用该关键词声明变量后,虚拟机会特别小心地处理,保证该变量的可见性。
但 volatile 不能代替锁,也无法保证一些复合操作的原子性。


15、线程组:

ThreadGroup tg = new ThreadGroup("TGroup");
Thread t1 = new Thread(tg, new ThreadGroupName(), "T1");
Thread t2 = new Thread(tg, new ThreadGroupName(), "T2");

tg.activeCount()

tg.list();


16、守护线程( Daemon),与之对应的是用户线程。

Thread t = new DaemonT();
t.setDaemon(true);  //必须在 start()方法前设置。
t.start();


17、线程优先级:

java中,线程优先级从1到10。

高优先级的线程竞争资源时会更有优势,但并不绝对。


18、线程安全的概念:

1)、synchronized 的基本用法:

   a、指定加锁对象:对给定对象加锁,进入同步代码前要获得给定对象的锁。

   b、直接作用于实例方法:相当于对当前实例加锁,进入同步代码前要获得当前实例的锁。

   c、直接作用于静态方法:相当于对当前类加锁,进入同步代码前要获得当前类的锁。

问题: 这三种用法是锁的粒度范围不同?a和b 有什么区别?


二、线程池

1、工作方式:

      有一个队列,任务被提交到这个队列中(也可有多个队列)。一定数量的线程会从该队列中取任务,

      然后执行。执行完任务后,线程会从任务队列中取下一个任务并执行,如果没有任务要执行,则等待。

 2、线程池有最小线程数最大线程数,池中有最小数目的线程随时待命,等待任务指派给他们。

      最小线程数也叫核心池大小

      最大线程数是一个限流阀,防止一次执行太多线程。最大线程数的大小取决于负载特性以及底层硬件

     最优线程数还与每个任务的阻塞频率有关。


3、线程池Executor框架:

ThreadPoolExecutor

Executors 为线程池工厂,包含如下构造线程池的方法:

public staticExecutorServicenewFixedThreadPool() :

   返回一个固定线程数量的线程池。


public staticExecutorService newSingleThreadExecutor:

    返回只有一个线程的线程池。


public static
ExecutorService newCachedThreadPool

  返回一个可根据实际情况调整线程数量的线程池。线程池的线程数量不固定。

public staticScheduledExecutorServicenewSingleThreadScheduledExecutor

   返回一个 ScheduledExecutorService 对象,线程池大小为一。

   ScheduledExecutorService接口在ExecutorService 接口只上扩展了在给定时间执行某任务的功能。
    如在
某个固定时间执行某任务的功能,如在某个固定的延迟之后执行,或者周期性的执行某个任务。

public staticScheduledExecutorService  newScheduledThreadPool

   该方法也返回一个ScheduledExecutorService对象,但该线程可以指定线程数量。

public staticExecutorService  unconfigurableExecutorService

public static ScheduledExecutorService  unconfigurableScheduledExecutorService


20、JDK 并发容器:

CuncurrentHashMap:

CopyOnWriteArrayList:

ConcurrentLinkedQueue:

BlockingQueue:

ConcurrentSkipListMap:


问题

1、ActomicLong 类?

2、JUC(包括重入锁(Lock)、线程池/连接池(commom-pool)、Timer、Future模式、AQS、CAS等)

3、代理,反射