JUC详解1
JUC:java.util.concurrent
线程和进程
1、进程是指的一个程序,如一个qq.exe、IDEA.exe等
2、线程指打开一个进程后,如qq可打字发消息,这就是线程
一个进程往往含有多个线程(最少一个)
java默认含有2个线程:main、GC
java的三种开线程的方式:Thread、Runable、Callable
并发、并行
并发:多个线程操作同一个资源
- CPU一核:通过模拟多个线程,交替进行
并行:多个线程同时执行
- CPU多核:多个线程同时执行
//查询自己电脑的核数
System.out.println(Runtime.getRuntime().availableProcessors());
并发编程本质:充分利用CPU资源
线程
线程的状态
新生:NEW
运行:RUNNABLE
阻塞:BLOCKED
等待:WAITING
超时等待:IMED_WAITING
终止:TERMINATED
wait/sleep
wait–>Object(包不同)
wait会自己释放锁(锁的释放方式)
必须在同步代码块中(使用范围)
不需要捕获异常(异常的捕获)
sleep–>Thread
sleep不会自己释放锁
可以在任何地方使用
需要捕获异常
lock锁
看个栗子
public class Sync {
public static void main(String[] args) {
//线程就是一个单独的资源类,没有附属任何操作
Ticket ticket = new Ticket();
for (int i=0;i<50;i++){
new Thread(()->{ticket.sale();},"A").start();
new Thread(()->{ticket.sale();},"B").start();
new Thread(()->{ticket.sale();},"C").start();
}
}
}
/**
* 资源类
*/
class Ticket{
private int number=50;
public void sale(){
if (number > 0) {
System.out.println(Thread.currentThread().getName()+"这是第"+number--+"张票;还剩:"+number+"张票。");
}
}
}
运行情况:
运行的很乱,没有顺序,而且还出现了-1;
解决的原始方案:加synchronize
public synchronized void sale(){
if (number > 0) {
System.out.println(Thread.currentThread().getName()+"这是第"+number--+"张票;还剩:"+number+"张票。");
}
}
lock
可重入锁:ReentrantLock
默认为非公平锁:非公平锁,即有多个线程,那个线程执行块,执行那个
公平锁:一个一个,排队来,先来后到,非常公平;
但我们实际中都使用非公平锁;为什么呢?
- 你想一个线程需要2小时执行完,一个线程2秒执行完,如果公平,2小时的排在2秒的前,那么就得要先执行完两小时的,再等2秒的,这样肯定不太行
使用lock实现
public class LockTest {
public static void main(String[] args) {
Ticket ticket = new Ticket();
for (int i=0;i<50;i++){
new Thread(()->{ ticket.sale(); },"11").start();
new Thread(()->{ ticket.sale(); },"22").start();
new Thread(()->{ ticket.sale(); },"33").start();
}
}
}
/**
* lock三步曲
* 1、new ReentrantLock();
* 2、加锁:lock.lock();
* 3、解锁:lock.unlock();
*/
class Ticket{
private int number=50;
Lock lock = new ReentrantLock();
public void sale(){
//加锁
lock.lock();
try {
//业务代码
if (number > 0) {
System.out.println(Thread.currentThread().getName()+"这是第"+number--+"张票;还剩:"+number+"张票。");
}
}catch (Exception e){
e.printStackTrace();
}finally {
//解锁
lock.unlock();
}
}
}
synchronized和lock的区别
- synchronized是一个java的内置的关键字,而lock是一个java类
- synchronized无法判断锁的状态,而lock可以判断是否获取到
- synchronized是全自动的,会自动加锁释放锁;lock必须手动释放锁,否则会出现死锁
- synchronized:线程1(获得锁,阻塞),线程2(等待,直到线程1释放锁);lock:可以获取锁:lock.tryLock();
- synchronized:可重入锁,非公平,不可中断;lock:可重入锁,非公平(可自由设置),可以判断锁的状态;
- synchronized:适合使用锁少量代码同步问题;lock:适合锁大量同步代码
补充
可重入锁是指:同一个线程可以获取同一把锁多次
重入锁实现可重入性原理或机制是:每一个锁关联一个线程持有者和计数器,当计数器为 0 时表示该锁没有被任何线程持有,那么任何线程都可能获得该锁而调用相应的方法;当某一线程请求成功后,JVM会记下锁的持有线程,并且将计数器置为 1;此时其它线程请求该锁,则必须等待;而该持有锁的线程如果再次请求这个锁,就可以再次拿到这个锁,同时计数器会递增;当线程退出同步代码块时,计数器会递减,如果计数器为 0,则释放该锁。
下一篇:JUC详解2——生产者消费者