Java无法直接开启线程,它是运行在虚拟机上的,无法操作硬件,start方法调用底层的c++
并发:多个线程操作同一个资源类
并发编程的本质:
充分利用CPU的资源
线程的6个状态:
NEW
RUNNABLE
BLOCKED
WAITING
TIMED_WAITING
TERMINATED
创建线程不要继承接口了,注意解耦和
防止线程的虚假唤醒,判断条件不能用if,而是要用while。
拿两个加法线程A、B来说,比如A先执行,执行时调用了wait方法,那它会等待,此时会释放锁,那么线程B获得锁并且也会执行wait方法,两个加线程一起等待被唤醒。此时减线程中的某一个线程执行完毕并且唤醒了这俩加线程,那么这俩加线程不会一起执行,其中A获取了锁并且加1,执行完毕之后B再执行。如果是if的话,那么A修改完num后,B不会再去判断num的值,直接会给num+1。如果是while的话,A执行完之后,B还会去判断num的值,因此就不会执行。
用condition可以精确的唤醒线程
public class text {
public static void main(String[] args) {
final data1 data = new data1();
new Thread(()->{
for (int i = 0; i < 10; i++) {
data.pra();
}
},"A").start();
new Thread(()->{
for (int i = 0; i < 10; i++) {
data.prb();
}
},"B").start();
new Thread(()->{
for (int i = 0; i < 10; i++) {
data.prc();
}
},"C").start();
}
}
class data1{ //资源类 look
private Lock lock =new ReentrantLock();
Condition condition1 = lock.newCondition();
Condition condition2 = lock.newCondition();
Condition condition3 = lock.newCondition();
int number = 1;
public void pra() {
lock.lock();
try {
while (number!=1){
condition1.await();
}
System.out.println(Thread.currentThread().getName()+"=>AAAAA");
number = 2;
condition2.signal(); //精确唤醒
}catch (Exception E){
E.printStackTrace();
}finally {
lock.unlock();
}
}
public void prb() {
lock.lock();
try {
while (number!=2){
condition2.await();
}
System.out.println(Thread.currentThread().getName()+"=>BBBBBB");
number = 3;
condition3.signal(); //精确唤醒
}catch (Exception E){
E.printStackTrace();
}finally {
lock.unlock();
}
}
public void prc() {
lock.lock();
try {
while (number!=3){
condition3.await();
}
System.out.println(Thread.currentThread().getName()+"=>CCCCC");
number = 1;
condition1.signal(); //精确唤醒
}catch (Exception E){
E.printStackTrace();
}finally {
lock.unlock();
}
}
}
synchronized关键字
锁的对象是方法的调用者
同一个类下的方法 都用synchronized修饰的话 用的是同一把锁 哪个方法先拿到 哪个方法先执行(同一个类创建多个对象来调用除外)
但是如果是同步的静态方法,创建多少个类对象,都只能共抢一把锁,因为锁的是class,全局唯一。
普通方法不受锁的影响