前置知识:
JUC
:java.util工具包java默认线程
:有两个默认线程,main,GC- java真的可以开启线程吗?
不可以
,调用本地方法,底层的C++,Java无法直接操作硬件 - 并发:多线程操作同一个资源
CPU一核
:快速交替,模拟出多线程
CPU多核
:多个线程可以同时执行
获取CPU核数
:Runtime.getRuntime().availableProcessors()
package day1;
/**
* @author jitwxs
* @date 2021年05月11日 17:15
*/
public class main {
public static void main(String[] args) {
System.out.println(Runtime.getRuntime().availableProcessors());
}
}
并发编程的实质
:充分利用CPU资源线程6个状态
:- 新生NEW,运行RUNNABLE,阻塞BLOCKED,等待WAITING,超时等待TIMED_WAITING,终止TERMINATED
wait和sleep的区别
:- 来自不同的类,wait来自Object,sleep来自Thread
- 企业中休眠会用:
TimeUnit.DAYS.sleep(1)
(睡一天) - 关于锁的释放:wait会释放锁,sleep不会释放锁
- 使用的范围:sleep可以在任何地方使用,
wait必须在同步代码块中
- 是否需要捕获异常:wait不需要捕获异常,sleep需要捕获异常
Lock锁(重点):
synchronized
package day1;
/**
* @author jitwxs
* @date 2021年05月11日 19:48
*/
//买票的例子,真正的开发过程中,降底耦合性
//线程就是一个单独的资源类
public class SealTicket {
public static void main(String[] args) {
//并发,多个线程操作一个资源类,把资源类丢入线程
Ticket ticket = new Ticket();
new Thread(()->{
for (int i = 0; i < 40; i++) {
ticket.seal();
}
},"A").start();
new Thread(()->{
for (int i = 0; i < 40; i++) {
ticket.seal();
}
},"B").start();
new Thread(()->{
for (int i = 0; i < 40; i++) {
ticket.seal();
}
},"c").start();
}
}
//资源类 OOP
class Ticket{
//属性方法
private int num = 50;
//买票的方式
//synchronized 本质:队列,锁
public synchronized void seal(){
if (num>0){
System.out.println(Thread.currentThread().getName()+"卖出了"+(num--)+"票,"+"剩余:"+num);
}
}
}
Lock接口
:
- Lock lock = new ReentrantLock(boolean); true为公平锁,false为非公平锁
- 公平锁:可以先来后到
- 非公平锁:
可以插队(默认)
package day2;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* @author jitwxs
* @date 2021年05月11日 19:48
*/
//买票的例子,真正的开发过程中,降底耦合性
//线程就是一个单独的资源类
public class SealTicket {
public static void main(String[] args) {
//并发,多个线程操作一个资源类,把资源类丢入线程
Ticket ticket = new Ticket();
new Thread(()->{
for (int i = 0; i < 40; i++) {
ticket.seal();
}
},"A").start();
new Thread(()->{
for (int i = 0; i < 40; i++) {
ticket.seal();
}
},"B").start();
new Thread(()->{
for (int i = 0; i < 40; i++) {
ticket.seal();
}
},"c").start();
}
}
//Lock
class Ticket{
//属性方法
private int num = 50;
Lock lock = new ReentrantLock();
//买票的方式
public void seal(){
lock.lock(); //加锁
try {
if (num>0){
System.out.println(Thread.currentThread().getName()+"卖出了"+(num--)+"票,"+"剩余:"+num);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock(); //解锁
}
}
}
synchronized 和 Lock的区别
:
- synchronized 内置的java关键字,Lock是一个java类
- synchronized 无法判断获取锁的状态,Lock可以判断是否获取到了锁
- synchronized 会自动释放锁,Lock必须手动释放锁,如果不释放就是
死锁
- synchronized 线程1(获得锁,阻塞),线程2(等待,傻傻的等);Lock锁不应定会等待下去(lock.tryLock()尝试获取锁)
- synchronized 可重入锁,不可以中断,非公平;Lock可重入锁,可以判断锁,非公平(可以自己设置)
- synchronized 适合锁少量的代码同步问题;Lock适合锁大量的同步代码