同步:A去公司前台找B,B不在,A一直等B。
异步:A去公司前台找B,B不在,A回去了,B什么时候在了通知A。
并发:一个饮水机,大家交替接水喝。
并行:两个饮水机,两个人同时接水喝。
A和B同时进一个厕所,只有一个人可以进厕所。
提高系统性能
java memory model 翻译为 java 内存模型
线程一修改共享变量是否对线程二可见。
一系列操作是否是一个不可分割的,也就是常说的同时成功或同时失败。
指令重排序,不是按照写代码的顺序进行执行。
public enum State {
NEW,
RUNNABLE,
BLOCKED,
WAITING,
TIMED_WAITING,
TERMINATED;
}
下面我们用一个实例来看看线程的所有状态
public class UseThread {
static UseThread obj = new UseThread();
public static void main(String[] args) throws Exception {
Thread t1 = new Thread(() -> {
UseThread.testBlock();
}, "thread-01");
Thread t2 = new Thread(() -> {
UseThread.testBlock();
}, "thread-02");
//线程t2创建 new
System.out.println(System.currentTimeMillis() + " " + t2.getName() + ":" + t2.getState());
t1.start();
t2.start();
//线程二启动 RUNNABLE
System.out.println(System.currentTimeMillis() + " " + t2.getName() + ":" + t2.getState());
while (true) {
Thread.sleep(100);
System.out.println(System.currentTimeMillis() + " " + t2.getName() + ":" + t2.getState());
if ("TERMINATED".equals(t2.getState().toString())) {
break;
}
}
System.out.println("------");
Thread t3 = new Thread(() -> {
UseThread.testWait();
}, "thread-03");
Thread t4 = new Thread(() -> {
UseThread.testNotify();
}, "thread-04");
t3.start();
Thread.sleep(50);
System.out.println(System.currentTimeMillis() + " " + t3.getName() + ":" + t3.getState());
t4.start();
}
public static void testBlock() {
synchronized (obj) {
System.out.println(System.currentTimeMillis() + " " + Thread.currentThread().getName() + "抢到了锁");
try {
Thread.sleep(200);
} catch (InterruptedException e) {
}
System.out.println(System.currentTimeMillis() + " " + Thread.currentThread().getName() + "释放锁");
}
}
public static void testWait() {
synchronized (obj) {
System.out.println(System.currentTimeMillis() + " " + Thread.currentThread().getName() + "抢到了锁");
try {
obj.wait();
System.out.println(System.currentTimeMillis() + " " + Thread.currentThread().getName() + "我被唤醒了");
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(System.currentTimeMillis() + " " + Thread.currentThread().getName() + "释放锁");
}
}
public static void testNotify() {
synchronized (obj) {
System.out.println(System.currentTimeMillis() + " " + Thread.currentThread().getName() + "抢到了锁");
obj.notify();
System.out.println(System.currentTimeMillis() + " " + Thread.currentThread().getName() + "释放锁");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
}
}
}
--------
1656144877610 thread-02:NEW
1656144877610 thread-02:RUNNABLE
1656144877611 thread-01抢到了锁
1656144877712 thread-02:BLOCKED
1656144877813 thread-01释放锁
1656144877813 thread-02抢到了锁
1656144877814 thread-02:TIMED_WAITING
1656144877914 thread-02:TIMED_WAITING
1656144878014 thread-02:TIMED_WAITING
1656144878015 thread-02释放锁
1656144878114 thread-02:TERMINATED
------
1656144878114 thread-03抢到了锁
1656144878165 thread-03:WAITING
1656144878165 thread-04抢到了锁
1656144878165 thread-04释放锁
1656144879169 thread-03我被唤醒了
1656144879169 thread-03释放锁
结果分析:
线程二刚创建的状态为 NEW ,执行start方法后变为RUNNABLE,线程t1持有锁的200毫秒内,t2是BLOCKED状态。t2持有锁的过程中睡眠200毫秒是TIMED_WAITING状态。t2执行完后是TERMINATED状态。
聊到juc就不得不提一下 Doug Lea 并发包之父


接口直接返回success,两秒后异步线程完毕,执行方法a。
@Override
public String test() {
CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
stringRedisTemplate.opsForValue().set("k1", "v1");
log.info("{} sync k1 v1 ...", Thread.currentThread().getName());
});
future.whenComplete((r, e) -> {
a();
});
log.info("start return ...");
return "succes";
}
public void a() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
log.info("{} sync k2 v2 ...", Thread.currentThread().getName());
stringRedisTemplate.opsForValue().set("k2", "v2");
}

有返回值,通过whenComplete方法的r和e来获取相应的执行结果和异常。
@Override
public String test() {
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
stringRedisTemplate.opsForValue().set("k1", "v1");
log.info("{} sync k1 v1 ...", Thread.currentThread().getName());
return "this is result ";
});
future.whenComplete((r, e) -> {
log.info("result = {} error = {}", r, e.getMessage());
a();
});
log.info("start return ...");
return "succes";
}
public void a() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
log.info("{} sync k2 v2 ...", Thread.currentThread().getName());
stringRedisTemplate.opsForValue().set("k2", "v2");
}

我们将代码稍作改造,获取异常。


获取执行结果,默认为异步,由异步线程1执行任务a。

由异步线程2执行任务a。


修改为get则会阻塞直到任务完成

可以看到接口返回的结果已经发生改变。
