1.什么是JUC
java.util工具包、包、分类
业务:普通业务线程代码 Thread
Runable: 没有返回值、效率相比Callable相对较低。
2.线程和进程
进程:一个程序,QQ.exe Music.exe 程序的集合
一个进程往往可以包含多个线程,至少包含一个!
java默认有几个线程?2个 main GC
线程:开了一个进程Typora,写字,自动保 存(线程负责)
对于java而言:Thread、Runable、Callable
**java可以开启线程吗?**不可以(本地方法,底层C++,java无法操作硬件)
并发、并行
并发(多线程操作同一个资源)
并行(多个人一起走)
- CPU多核,多线程可以同时执行;线程池
并发编程的本质:充分利用CPU资源
3.Synchronized和Lock
Synchronized和Lock的区别
- Synchronized内置的Java关键字,Lock是一个Java类
- Synchronized无法判断获取锁的状态,Lock可以判断是否获取到了锁
- Synchronized会自动释放锁,Lock必须手动释放锁!如果不释放锁就会–死锁
- Synchronized线程1(获得锁、阻塞)、线程2(等待,傻傻的等),Lock锁就不一定等待下去。
- Synchronized可重入锁,不可以中断的,非公平;Lock,可重入锁,可以判断锁,非公平(可以自己设置)。
- Synchronized适合锁少量的代码同步问题,Lock适合锁大量的同步代码。
4.生产者和消费者
传统的生产者和消费者的问题、防止虚假唤醒
线程也可以唤醒,而不会被通知、中断或超时,即所谓虚假唤醒
if语句只能判断一次,在等待的时候如果另一个线程修改了数据,那么wait后就不会进行if判断了
public class A {
public static void main(String[] args) {
Data data = new Data();
new Thread(()->{
for (int i = 0; i < 5; i++) {
try {
data.increment();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"A").start();
new Thread(()->{
for (int i = 0; i < 5; i++) {
try {
data.decrement();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"B").start();
new Thread(()->{
for (int i = 0; i < 5; i++) {
try {
data.increment();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"C").start();
new Thread(()->{
for (int i = 0; i < 5; i++) {
try {
data.decrement();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"D").start();
}
}
class Data{
private int number=0;
public synchronized void increment() throws InterruptedException {
//这里使用while循环,如果使用if判断会出现虚假幻想的现象
while (number!=0){
this.wait();
}
number++;
System.out.println(Thread.currentThread().getName()+"=>"+number);
this.notifyAll();
}
public synchronized void decrement() throws InterruptedException {
//同理
while (number==0){
this.wait();
}
number--;
System.out.println(Thread.currentThread().getName()+"=>"+number);
this.notifyAll();
}
}
Lock锁实现生产者消费者的问题,Condition实现精准通知唤醒
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class C {
public static void main(String[] args) {
Data3 data = new Data3();
new Thread(()->{
for (int i = 0; i < 5; i++) {
data.printA();
}
},"A").start();
new Thread(()->{
for (int i = 0; i < 5; i++) {
data.printB();
}
},"B").start();
new Thread(()->{
for (int i = 0; i < 5; i++) {
data.printC();
}
},"C").start();
}
}
class Data3{
private int number=1;
Lock lock=new ReentrantLock();
Condition condition1=lock.newCondition();
Condition condition2=lock.newCondition();
Condition condition3=lock.newCondition();
public void printA(){
lock.lock();
try {
while (number!=1){
//等待
condition1.await();
}
System.out.println(Thread.currentThread().getName()+"=>"+number);
number=2;
//唤醒所有线程
condition2.signal();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void printB(){
lock.lock();
try {
while (number!=2){
//等待
condition2.await();
}
System.out.println(Thread.currentThread().getName()+"=>"+number);
number=3;
//唤醒所有线程
condition3.signal();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void printC(){
lock.lock();
try {
while (number!=3){
//等待
condition3.await();
}
System.out.println(Thread.currentThread().getName()+"=>"+number);
number=1;
//唤醒所有线程
condition1.signal();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
文章评论