1什么式JUC
Java.uitl工具包
包,分类
业务:普通的线程代码Thread
Runnable 没有返回值,效率相比于Callable相对较低
Java.util.concurrent包下的
Lock锁在Java.util.concurren.locks下
2线程和进程
进程:一个程序,QQ.exe,mysic.exe程序的集合;
一个进程往往包含多个线程;至少包含一个
Java默认有几个线程?2个 main和GC线程
线程:开了一个进程:Typora,写字,自动保存(线程负责的)
对于java而言Thread,Runnble,Callable
Java真的可以开启线程吗?
开不了的
Thread部分源码
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++ java无法直接操作硬件
private native void start0();
并发、并行
并发(多线程操作同一个资源)
- CPU单核,模拟出来多条线程,天下武功,唯快不破,快速交替
并行(多个人一次行走)
- CPU多核,多个线程可以同时执行;线程池
查询cpu核数
public class Test1 {
public static void main(String[] args) {
//查询cpu核数
//CPU 密集型,IO密集型
System.out.println(Runtime.getRuntime().availableProcessors());
}
}
并发编程的本质:充分利用CPU的资源
03.回顾多线程
线程有几个状态 – 6种
public enum State {
/**
* 新建
*/
NEW,
/**
* 运行
*/
RUNNABLE,
/**
* 阻塞
*/
BLOCKED,
/**
* 等待,死死的等
*/
WAITING,
/**
* 超时等待
*/
TIMED_WAITING,
/**
* 停止
*/
TERMINATED;
}
wait/sleep区别
- 来自不同的类
wait -> Object
sleep -> Thread
- 关于锁的释放
wait会释放锁
sleep睡觉了,抱着锁睡觉,不会释放!
- 使用的范围是不同的
wait必须在同步代码块中
sleep可以在任何地方睡
- 是否需要捕获异常
wait不需要捕获异常
sleep必须捕获异常
04.传统的Synchronized锁
public class SaleTickerDemo01 {
public static void main(String[] args) {
Ticket ticket = new Ticket();
new Thread(() -> {
for (int i = 0; i < 50; i++) {
ticket.sale();
}
}, "A").start();
new Thread(() -> {
for (int i = 0; i < 50; i++) {
ticket.sale();
}
}, "B").start();
new Thread(() -> {
for (int i = 0; i < 50; i++) {
ticket.sale();
}
}, "C").start();
}
}
class Ticket {
private int number = 50;
public synchronized void sale() {
if (number > 0) {
System.out.println(Thread.currentThread().getName() + "买了第" + (number--) + "张票");
}
}
}
输出
A买了第50张票
A买了第49张票
A买了第48张票
A买了第47张票
A买了第46张票
A买了第45张票
B买了第44张票
B买了第43张票
B买了第42张票
B买了第41张票
B买了第40张票
B买了第39张票
B买了第38张票
B买了第37张票
B买了第36张票
B买了第35张票
B买了第34张票
B买了第33张票
B买了第32张票
B买了第31张票
B买了第30张票
B买了第29张票
B买了第28张票
B买了第27张票
B买了第26张票
B买了第25张票
B买了第24张票
B买了第23张票
A买了第22张票
A买了第21张票
A买了第20张票
A买了第19张票
A买了第18张票
A买了第17张票
A买了第16张票
A买了第15张票
A买了第14张票
A买了第13张票
A买了第12张票
A买了第11张票
A买了第10张票
A买了第9张票
A买了第8张票
A买了第7张票
A买了第6张票
A买了第5张票
A买了第4张票
A买了第3张票
A买了第2张票
A买了第1张票
05.Lock锁
加锁,释放锁
实现类(可重入锁,读锁,写锁)
可重入锁构造方法
公平锁:十分公平,可以先来后到
非公平锁:十分不公平,可以插队(默认)
public class SaleTickerDemo02 {
public static void main(String[] args) {
Ticket2 ticket = new Ticket2();
new Thread(() -> {
for (int i = 0; i < 50; i++) {
ticket.sale();
}
}, "A").start();
new Thread(() -> {
for (int i = 0; i < 50; i++) {
ticket.sale();
}
}, "B").start();
new Thread(() -> {
for (int i = 0; i < 50; i++) {
ticket.sale();
}
}, "C").start();
}
}
/**
* 1.创建锁 Lock lock = new ReentrantLock();
* 2.加锁 lock.lock();
* 3.释放锁 lock.unlock();
*/
class Ticket2 {
private int number = 50;
/**
* 创建锁
*/
Lock lock = new ReentrantLock();
public void sale() {
//加锁
lock.lock();
try {
if (number > 0) {
System.out.println(Thread.currentThread().getName() + "买了第" + (number--) + "张票");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
//释放锁
lock.unlock();
}
}
}
06.Synchronized和Lock区别
- Synchronized 内置的java关键字,Lock是一个java类
- Synchronized 无法判断获取锁的状态,Lock可以判断是否获取到了锁
- Synchronized 会自动释放锁,Lock必须手动释放锁,如果不释放锁,会导致死锁!
- Synchronized 线程1(获得锁,阻塞)、线程2(等待,傻傻的等);Lock就不一定会等待下去
- Synchronized,可重入锁,不可以中断,非公平;Lock,可重入锁,可以判断锁,非公平(自己可以设置)
- Synchronized 使用锁少量的代码同步问题,Lock适合锁大量的同步代码