java.util 工具包
业务:普通的线程代码 Thread
Runnable:没有返回值,效率相比 Callable 相对较低
进程:一个程序,QQ.exe、Music.exe
一个进程往往可以包含多个线程,至少包含一个
java 默认 有两个线程:main线程 gc线程(垃圾回收)
线程:开了一个进程 world ,写字,自动保存(线程负责的)
对于java:Thread、Runnable、Callable
java真的可以开启线程吗? 不能 java无法直接操作硬件
本地方法,底层的c++,java无法直接操作硬件
private native void start()
线程有几个状态?
新生、运行、阻塞、等待、超时等待、终止
wait/sleep 区别
来自不同的类
? wait => Object
? sleep => Threat
关于锁的释放
wait会释放锁
sleep 不会释放,睡觉了,抱着不放
使用的范围是不同的
wait:要在同步代码块中
sleep 可以在任意地方睡
是否需要捕获异常
wait 不需要捕获异常
sleep 必须要捕获异常
并发:多线程操作同一个资源,交替进行、
并行:多个人一起行走,同时进行
//获取cpu的核数
//CPU密集型,IO密集型
System.out.println(Runtime.getRuntime().availableProcessors());
并发编程的本质:充分利用cpu的资源
传统 synchronized
/**
* 真正的多线程开发,公司中的开发,降低低耦合
* 线程就是一个单独的资源类,没有任何附属的操作
* **/
public class SaleTicketDemo1 {
public static void main(String[] args) {
//并发:多线程操作同一个资源类,把资源丢入线程
Ticket1 ticket = new Ticket1();
new Thread(()->{
for (int i = 0; i < 40; i++) {
ticket.saleTicket();
}
},"A").start();
new Thread(()->{
for (int i = 0; i < 40; i++) {
ticket.saleTicket();
}
},"B").start();
new Thread(()->{
for (int i = 0; i < 40; i++) {
ticket.saleTicket();
}
},"C").start();
}
}
//资源类
class Ticket1{
private int number = 30;
public synchronized void saleTicket(){
if (number > 0){
System.out.println(Thread.currentThread().getName() + "买了第" + number-- + "票" + "还有" + number + "张票");
}
}
}
Lock锁
公平锁:十分公平;可以先来后到
非公平锁:十分不公平,可以插队(默认 )
Lock三部曲:
Lock lock = new ReentrantLock();
lock.lock();//加锁
finally => lock.unlock();//解锁
public class SaleTicketDemo2 {
public static void main(String[] args) {
Ticket1 ticket1 = new Ticket1();
//并发:多线程操作同一个资源类,把资源丢入线程
new Thread(()->{for (int i = 0; i < 40; i++) ticket1.saleTicket();},"A").start();
new Thread(()->{ for (int i = 0; i < 40; i++) ticket1.saleTicket(); },"B").start();
new Thread(()->{ for (int i = 0; i < 40; i++) ticket1.saleTicket(); },"C").start();
}
}
//资源类
class Ticket2 {
private int number = 30;
Lock lock = new ReentrantLock();
public void saleTicket() {
lock.lock();//加锁
try {
//业务代码
if (number > 0) {
System.out.println(Thread.currentThread().getName() + "买了第" + number-- + "票" + "还有" + number + "张票");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();//解锁
}
}
}
Synchronized 和 Lock 区别
线程之间的通信问题! 等待唤醒,通知唤醒
线程交替执行 A B 操作同一个变量 num = 0
A num + 1
B num - 1
public class A {
public static void main(String[] args) {
Data data = new Data();
new Thread(()->{
for (int i = 0; i <10 ;i++) {
try {
data.increment();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"A").start();
new Thread(()->{
for (int i = 0; i <10 ;i++) {
try {
data.decrement();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"B").start();
}
}
//判断等待、业务、通知
class Data{
private int number = 0;
public synchronized void increment() throws InterruptedException {
if (number != 0){
//等待
this.wait();
}
number++;
System.out.println(Thread.currentThread().getName() + "=>"+number);
//通知其他线程,我+1完毕了
this.notifyAll();
}
public synchronized void decrement() throws InterruptedException {
if (number == 0){
//等待
this.wait();
}
number--;
//通知其他线程,我-1完毕了
System.out.println(Thread.currentThread().getName() + "=>"+number);
this.notifyAll();
}
}
问题存在,A B C D 4个线程! 虚假唤醒
线程也可以唤醒,而不会被通知,中断或超时,即所谓的虚假唤醒。等待应该总是出现在循环中
当一个条件满足时,很多线程都被唤醒了,但是只有其中部分是有用的唤醒,其它的唤醒都是无用的唤醒;
if改为while判断
理解:两个加法线程A、C来说,比如A先执行,执行时调用了wait方法,此时会释放锁,接着如果线程C获得锁并且也会执行wait方法,两个加线程一起等待被唤醒。此时减线程中的B线程执行完毕并且唤醒了这俩加线程,那么这俩加线程不会一起执行,其中A获取了锁并且加1,执行完毕之后B再执行。如果是if的话,那么A修改完num后,B不会再去判断num的值,直接会给num+1。如果是while的话,A执行完之后,B还会去判断num的值,因此就不会执行。
public class A {
public static void main(String[] args) {
Data data = new Data();
new Thread(()->{
for (int i = 0; i <10 ;i++) {
try {
data.increment();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"A").start();
new Thread(()->{
for (int i = 0; i <10 ;i++) {
try {
data.decrement();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"B").start();
new Thread(()->{
for (int i = 0; i <10 ;i++) {
try {
data.increment();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"C").start();
new Thread(()->{
for (int i = 0; i <10 ;i++) {
try {
data.decrement();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"D").start();
}
}
//判断等待、业务、通知
class Data{
private int number = 0;
public synchronized void increment() throws InterruptedException {
while (number != 0){
//等待
this.wait();
}
number++;
System.out.println(Thread.currentThread().getName() + "=>"+number);
//通知其他线程,我+1完毕了
this.notifyAll();
}
public synchronized void decrement() throws InterruptedException {
while (number == 0){
//等待
this.wait();
}
number--;
//通知其他线程,我-1完毕了
System.out.println(Thread.currentThread().getName() + "=>"+number);
this.notifyAll();
}
}
juc版的生产者和消费者问题
原文:https://www.cnblogs.com/flypigggg/p/14696916.html