什么是JUC
java.util .concurrent 工具包
线程和进程
- 进程 :运行起来的程序
- 一个进程最少包含一个线程
- 线程: java默认有几个线程 2个 main 和GC
Java真的能够开启一个线程吗?
- 是不能的 他是调用的本地的方法去开启一个线程
public synchronized void start() {
/**
* This method is not invoked for the main method thread or "system"
* group threads created/set up by the VM. Any new functionality added
* to this method in the future may have to also be added to the VM.
*
* A zero status value corresponds to state "NEW".
*/
if (threadStatus != 0)
throw new IllegalThreadStateException();
/* Notify the group that this thread is about to be started
* so that it can be added to the group's list of threads
* and the group's unstarted count can be decremented. */
group.add(this);
boolean started = false;
try {
start0();
started = true;
} finally {
try {
if (!started) {
group.threadStartFailed(this);
}
} catch (Throwable ignore) {
/* do nothing. If start0 threw a Throwable then
it will be passed up the call stack */
}
}
}
//调用底层c++ 来操作硬件
private native void start0();
并发和并行区别
- 并发才会有多线程
- 单核CPU通过快速交替模拟并发
- 并行 多人一起行走
- 多核CPU可以实现并行
public static void main(String[] args) {
//获取CPU的核数 返回的是可用的计算资源
System.out.println(Runtime.getRuntime().availableProcessors());
}
线程的六种状态
public enum State {
/**
* Thread state for a thread which has not yet started.
*/
//新生
NEW,
/**
* Thread state for a runnable thread. A thread in the runnable
* state is executing in the Java virtual machine but it may
* be waiting for other resources from the operating system
* such as processor.
*/
//运行
RUNNABLE,
/**
* Thread state for a thread blocked waiting for a monitor lock.
* A thread in the blocked state is waiting for a monitor lock
* to enter a synchronized block/method or
* reenter a synchronized block/method after calling
* {@link Object#wait() Object.wait}.
*/
// 阻塞
BLOCKED,
/**
* Thread state for a waiting thread.
* A thread is in the waiting state due to calling one of the
* following methods:
* <ul>
* <li>{@link Object#wait() Object.wait} with no timeout</li>
* <li>{@link #join() Thread.join} with no timeout</li>
* <li>{@link LockSupport#park() LockSupport.park}</li>
* </ul>
*
* <p>A thread in the waiting state is waiting for another thread to
* perform a particular action.
*
* For example, a thread that has called <tt>Object.wait()</tt>
* on an object is waiting for another thread to call
* <tt>Object.notify()</tt> or <tt>Object.notifyAll()</tt> on
* that object. A thread that has called <tt>Thread.join()</tt>
* is waiting for a specified thread to terminate.
*/
// 等待 死等
WAITING,
/**
* Thread state for a waiting thread with a specified waiting time.
* A thread is in the timed waiting state due to calling one of
* the following methods with a specified positive waiting time:
* <ul>
* <li>{@link #sleep Thread.sleep}</li>
* <li>{@link Object#wait(long) Object.wait} with timeout</li>
* <li>{@link #join(long) Thread.join} with timeout</li>
* <li>{@link LockSupport#parkNanos LockSupport.parkNanos}</li>
* <li>{@link LockSupport#parkUntil LockSupport.parkUntil}</li>
* </ul>
*/
//超时等待
TIMED_WAITING,
/**
* Thread state for a terminated thread.
* The thread has completed execution.
*/
//死亡 终止
TERMINATED;
}
wait/sleep 区别
- 来自不同的类
- wait =>Object
- sleep=> Thread
- 锁的释放
- wait会释放锁,sleep睡觉 不会释放
- 使用范围不同
- wait 在同步的代码块当中
- sleep 可以在任何地方加
- 是否需要捕获异常
- wait 需要中断异常
- sleep需要捕获异常
Lock锁
-
synchronized 本质为排队 同步
-
public class LockDemo { public static void main(String[] args) { Monney monney = new Monney(); new Thread(()->{ for (int i = 0; i < 70; i++) { monney.quqian(); } },"a").start(); new Thread(()->{ for (int i = 0; i < 70; i++) { monney.quqian(); } },"b").start(); } } class Monney{ int num = 100; // Lock lock = new ReentrantLock(); public synchronized void quqian(){ // lock.lock(); if(num>0) { System.out.println(Thread.currentThread().getName() + num-- + "取钱成功"); } // lock.unlock(); } }
-
-
Lock
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oCML3CjB-1646231988370)(D:\桌面\截图\image-20220221143707889.png)]
public class LockDemo {
public static void main(String[] args) {
Monney monney = new Monney();
new Thread(()->{
for (int i = 0; i < 70; i++) {
monney.quqian();
}
},"a").start();
new Thread(()->{
for (int i = 0; i < 70; i++) {
monney.quqian();
}
},"b").start();
}
}
class Monney{
int num = 100;
Lock lock = new ReentrantLock();
public void quqian(){
lock.lock();
if(num>0) {
System.out.println(Thread.currentThread().getName() + num-- + "取钱成功");
}
lock.unlock();
}
}
synchronized 和Lock 区别
- synchronized 是内置的java关键字,Lock是一个java接口
- synchronized 无法判断获取锁的状态,Lock可以判断是否获取到了锁
- synchronized 会自动释放锁,lock必须要手动释放锁!如果不是释放就会死锁
- synchronized 线程1(获得锁并且阻塞) 线程2 会一直等待下去; 二Lock锁不会一直等待下去 lock.tryLock() 方法会去尝试获取锁
- synchronized 可重入锁,不可中断的,非公平;Lock,可重入锁,可以 判断锁,非公平(可以自己设置)
- synchronized适合锁少量的代码同步问题, Lock适合锁大量的代码
公平锁和非公平锁
- 公平锁: 十分公平,先来后到
- 非公平锁:
Condition
- Condition可以精准的通知和唤醒线程 不再是线程去争抢CPU
public class ConditionDemo {
private Lock lock = new ReentrantLock();
private Condition condition1 = lock.newCondition();
private Condition condition2 = lock.newCondition();
private Condition condition3 = lock.newCondition();
private int number = 1; // 1唤醒A 2唤醒B 3唤醒C
public void printA(){
lock.lock();
try {
while(number!=1){
condition1.await();
}
System.out.println("AAAAAAAAA");
condition2.signal();
}catch (Exception e){
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void printB(){
lock.lock();
try {
while(number!=2){
condition2.await();
}
System.out.println("BBBBBBBBB");
condition3.signal();
}catch (Exception e){
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void printC(){
lock.lock();
try {
while(number!=1){
condition3.await();
}
System.out.println("CCCCCCC");
condition1.signal();
}catch (Exception e){
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
- synchronized 锁的对象是方法的调用者
- synchronized 如果加了static 锁的就是编译过的.class模板
List如何保证安全
以下方法会报错
java.util.ConcurrentModificationException 并发修改异常错误
public static void main(String[] args) {
List<String> list = new ArrayList<>();
for(int i =0;i<10;i++){
new Thread(()->{
list.add(UUID.randomUUID().toString().substring(0,5));
System.out.println(list);
}).start();
}
}
用concurrent包下的实现可以避免异常
- 原理: CopyOnWrite写入时复制 计算机程序设计领域的优化策略
- 在写入的时候避免覆盖,造成数据问题
public static void main(String[] args) {
List<String> list = new CopyOnWriteArrayList<>();
for(int i =0;i<10;i++){
new Thread(()->{
list.add(UUID.randomUUID().toString().substring(0,5));
System.out.println(list);
}).start();
}
}
同理可得 CopyOnWriteArraySet<>();
map线程安全的两种实现方式 多线程下 实际开发当中经常使用
//1
HashMap<String,String> map = new HashMap<>();
Collections.synchronizedMap(map);
//2
Map<String,String> map = new ConcurrentHashMap<>();