1.什么是JUC?

业务: 普通的线程代码 Thread
Runnable 没有返回值,效率相比较Callable较低!
2.线程和进程
线程.进程,如果不能使用一句话说出来的技术,不扎实!
进程: 一个程序,QQ.exe Music.exe 程序的集合;
一个进程往往可以包含多个线程,至少包含一个!
java 默认有几个线程? 2 个 main / GC 回收器
线程: 开了一个进程 Typora , 写字, 自动保存(线程负责的)
对于 java 而言,: Thread/Runnable/Callable
java 真的可以开启线程么? 开不了
/**
* Causes this thread to begin execution; the Java Virtual Machine
* calls the <code>run</code> method of this thread.
* <p>
* The result is that two threads are running concurrently: the
* current thread (which returns from the call to the
* <code>start</code> method) and the other thread (which executes its
* <code>run</code> method).
* <p>
* It is never legal to start a thread more than once.
* In particular, a thread may not be restarted once it has completed
* execution.
*
* @exception IllegalThreadStateException if the thread was already
* started.
* @see #run()
* @see #stop()
*/
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 多核,多个线程可以同时执行; 线程池
public static void main(String[] args){
// 获取cpu的核数
// cpu 密集型/IO 密集型
System.out.println(Runtime.getRuntime().availableProcessors());
}
线程有几种状态
public enum State {
/**
* 新生
*/
NEW,
/**
* 运行
*/
RUNNABLE,
/**
* 堵塞
*/
BLOCKED,
/**
* 等待,一直等待
*/
WAITING,
/**
* 超时等待
*/
TIMED_WAITING,
/**
* 中断,终止
*/
TERMINATED;
}
wait/sleep 区别
1. 来自不同的类
wait => Object
sleep => Thread
2. 关于锁的释放
wait 会释放锁, sleep 睡觉了,抱着锁睡觉,不会释放!
3. 使用的范围是不同的
wait
sleep 可以再任何地方睡
4. 是否需要捕获异常
wait 中断异常
sleep 必须要捕获异常
3. Lock锁(重点)
传统 Sychronized
public class syncDemo {
public static void main(String[] args){
Ticket1 ticket1 = new Ticket1();
new Thread(()->{for(int i=0;i<30;i++){ticket1.sale();}},"A").start();
new Thread(()->{for(int i=0;i<30;i++){ticket1.sale();}},"B").start();
new Thread(()->{for(int i=0;i<30;i++){ticket1.sale();}},"C").start();
}
}
// OOP 思想 资源类
class Ticket1{
private int ticknum=32;
public synchronized void sale(){
if(ticknum>0){
System.out.println("线程["+Thread.currentThread().getName()+"] 买了{"+ticknum--+"},剩余"+ticknum+"张票");
}
}
}
Lock接口
公平锁: 十分公平,可以先来后到
非公平锁: 十分不公平,可以插队(默认)
public class lockDemo {
public static void main(String[] args){
Ticket2 ticket2 = new Ticket2();
new Thread(()->{for(int i=0;i<30;i++){ticket2.sale();}},"A").start();
new Thread(()->{for(int i=0;i<30;i++){ticket2.sale();}},"B").start();
new Thread(()->{for(int i=0;i<30;i++){ticket2.sale();}},"C").start();
}
}
class Ticket2{
private int ticknum=32;
public void sale(){
ReentrantLock lock = new ReentrantLock();
lock.lock();
try{
if(ticknum>0){
System.out.println("线程["+Thread.currentThread().getName()+"] 买了{"+ticknum--+"},剩余"+ticknum+"张票");
}
}catch (Exception e){
}finally {
lock.unlock();
}
}
}
Synchronized 和 Lock 区别
1. Synchronized 内置的java关键字 , Lock 是一个java类;
2. Synchronized 无法获取锁的状态, Lock 可以通过判断是否获得到了锁;
3. Synchronized 会自动释放锁 , Lock 必须手动释放锁! 如果不释放,死锁;
4. Synchronized 线程1 (获得锁,堵塞) 线程2(等待,一直等待); Lock锁会 tryLock() 尝试获取锁;
5. Synchronized 可重入锁,不可中断,非公平; Lock ,可重入锁,可以判断锁,公平/非公平可设置;
6. Synchronized 适合少量的代码同步问题; Lock 适合锁大量的同步代码;
锁是什么,如何判断锁的是谁!
4. 生产者和消费者问题
生产者和消费者 Synchronized版
/**
* 线程通信问题: 生产者和消费者问题 等待唤醒,通知唤醒
* 线程之间交替执行 生产 消费 操作同一个变量 num=0
* --producerSync num+=1
* --consumerSync num-=1
*/
public class producerSync {
public static void main(String[] args){
Data data = new Data();
new Thread(()->{
for (int i = 0; i < 10; i++) {
try {
data.decrement();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"consumer").start();
new Thread(()->{
for (int i = 0; i < 10; i++) {
try {
data.increment();
} catch (InterruptedException e) {
e.printStackTrace();