Java 多线程

进程

 进程是针对系统而言,打开一个程序就有一个进程,进程有独立的内存空间,系统至少有一个进程。

线程

线程是进程的一个实体,是cpu调度的基本单位,一个进程可以有多个线程,多个线程之间共享该进程的内存,一个进程至少有一个线程。线程分为用户线程和守护线程,当所有用户线程都运行结束时,不论守护线程是否完成进程都会结束。

线程的生命周期

1.创建期(new)

  ⬇ 

2.启动期(start,execute)               ⬅            ⬅    

 ⬇⬆                                阻塞期(sleep,wait,同步锁)        

3.运行期(抢夺到cpu资源,cpu调度)       ⬆    

  ⬇                                              

4.死亡期(run方法结束,线程内抛出为捕获Exception或Error)

线程的创建

1.继承Thread类,重写run方法

2.实现Runnable接口,实现run方法

线程的启动

1.thread.start()

2.通过线程池 executor.execute(Runnable r)

线程的同步

1.原子性:一步完成的操作,不会被打断。例如单纯的赋值操作:i = 3;非原子性:例如i ++。

2.数据可见性  即数据在不同线程间的可见性,如果线程A改变了变量i的值其他线程能知道变量i的最新值

volatile关键字:volatile修饰的变量会在被修改后自动store,将该值从线程的内存中刷新到主内存中,在读取该变量之前自动load,将主内存中的值加载到线程内存中。该关键字可保证可见性但不保证原子性。

synchronized关键字:即同步,在进入同步块前会自动将主内存中的值加载到线程内存中,离开同步块之前会自动将值刷新到主内存中。可保证同步块内的数据可见性和操作原子性。

3.synchronized 关键字

在某一时刻,只有持有指定对象的锁的线程才能进入同步区域,保证当前时刻只有当前线程能修改同步数据,若其他线程想修改将会阻塞。

同步方法:在方法声明前加上synchronized,代表synchronized(this),持有当前对象的锁

同步块:又叫临界区,在方法体内,可指定同步锁

静态方法的同步:对象锁时当前类的class对象,与其他同步方法互不干扰

4.Lock类

Lock lock = new ReentrantLock()  可以设置是否公平

try {

lock.lock()  (lock.tryLock())   获取到该锁的线程可以进入

XXXX

XXXx

}finally{

lock.unlock()  在finally中保证所能够被释放

}

线程的调度

1.sleep()

线程休眠一段时间,不会释放对象锁

2.yiled()

礼让,当前线程从运行状态转为启动状态,让出cpu资源,所有线程再次抢夺,有可能还是当前线程抢到

3.join()

将一个线程强制运行,例如在A线程中调用b.join()则强制运行B线程直到B线程运行完后A线程才继续运行 

4.wait(),notify(),notifyAll()

wait()使当前线程挂起,暂时释放对象锁,可以指定等待时间

notify,notifyAll 唤醒一个或所有在该对象锁下等待的线程

这几个方法都必须在同步块或者同步方法内由当前锁对象调用

5.CountDownLatch

用于使A线程等待直到其他size个线程运行完,不可以重用

CountDownLatch count = new CountDownLatch(int size)

count.await() 使当前线程挂起,直到锁存器的计数为零,可指定等待时间

count.countDown()  锁存器计数器减一,指定任务完成后调用

count.getCount()  返回锁存器计数

6.CyclicBarrier

可以复用

CyclicBarrier barrier = new CyclicBarrier(int parties,Runnable r)

parties:该组线程的个数

r:可选参数,当所有线程都到达屏障后会执行该任务,该任务由最后一个到达屏障的线程执行

作用于一组线程,当他们全部都达到某个特定状态时才能继续运行,否则已经到达await()的线程将会被挂起

7.Semaphore

计数信号量

用于设置一个数据可以同时被几个线程访问,若只能一个的话就相当于互斥锁

Semaphore sema = new Semaphore(int permits,boolean isFair)

permits:允许的线程数量

isFair:如果设置为true的话,按先进先出的顺序授予许可

sema.acquire() 请求获取一个许可

sema.release() 释放一个许可

8.守护线程

在start()前调用thread.setDaemon()设置为后台线程

9.优先级

一共有十个优先级,从一到十

thread.setPriority()

优先级不能决定调用顺序

原文地址:https://www.cnblogs.com/xiao-ji-xiang/p/9819063.html