10. 异步执行,Volatile关键字,JMM
/** * @author wuyimin * @create 2021-07-10-14:37 * @description * 异步执行,成功回调,失败回调 */ public class demo01 { //今天才发现如果不是静态函数在java类内部的主函数是不能直接调用的 public static void main(String[] args) throws ExecutionException, InterruptedException { //NoReturn(); HasReturn(); } public static void NoReturn() throws ExecutionException, InterruptedException { //Void泛型表示没有返回值 CompletableFuture<Void> completableFuture=CompletableFuture.runAsync(()->{ try { TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"-void"); }); System.out.println("正在等待执行结果"); System.out.println(completableFuture.get());//null } public static void HasReturn() throws ExecutionException, InterruptedException { CompletableFuture<Integer> completableFuture=CompletableFuture.supplyAsync(()->{ System.out.println(Thread.currentThread().getName()+"Integer"); return 1024; }); //如果成功 Integer integer = completableFuture.whenComplete((t, u) -> { System.out.println("t=" + t);//正常的返回结果 System.out.println("u=" + u);//错误的返回结果 //如果失败 }).exceptionally((e) -> { System.out.println(e.getMessage()); return 233;//错误的返回结果返回 }).get(); System.out.println(integer); } }
4组-8个操作
规定:
保证可见性
public class JMM { private static int num=0; private volatile static int num2=0; public static void main(String[] args) { test02(); } //这个方法的执行结果是能打印出1但是程序一直在执行死循环 public static void test01(){ new Thread(()->{ while(num==0){ System.out.println("循环中"); } }).start(); try { TimeUnit.SECONDS.sleep(2); }catch (InterruptedException e){ e.printStackTrace(); } num=1; System.out.println(num); } //一开始在循环中,一旦num被修改就会停止,这里体现的是volatile关键字的可见性 public static void test02(){ new Thread(()->{ while(num2==0){ System.out.println("循环中"); } }).start(); try { TimeUnit.SECONDS.sleep(2); }catch (InterruptedException e){ e.printStackTrace(); } num2=1; System.out.println(num2); } }
不保证原子性
public class NoAtom { private volatile static int num=0;//即使加了volatile这个值依旧不是20000,但是 synchronized是保证的 private static void add(){ num++; } public static void main(String[] args) { //理论是20000 for (int i = 0; i <20; i++) { new Thread(()->{ for (int j = 0; j < 1000; j++) { add(); } }).start(); } while (Thread.activeCount()>2){//如果有超过两条线程在运行(java本身就有GC和main两条线程在进行) Thread.yield();//线程礼让 让main线程放弃cpu给别的线程,等到其他线程死了再继续main线程 } System.out.println(Thread.currentThread().getName()+" "+num); } }
如果不使用lock和synchronized如何保证原子性呢
num++并不是一个原子性操作,使用原子类来解决原子性问题
public class NoAtom { private volatile static AtomicInteger num=new AtomicInteger();//原子类的Integer private static void add(){ num.getAndIncrement();//类似num++但是是一个原子操作,CAS操作 } public static void main(String[] args) { //理论是20000 for (int i = 0; i <20; i++) { new Thread(()->{ for (int j = 0; j < 1000; j++) { add(); } }).start(); } while (Thread.activeCount()>2){//如果有超过两条线程在运行(java本身就有GC和main两条线程在进行) Thread.yield();//线程礼让 让main线程放弃cpu给别的线程,等到其他线程死了再继续main线程 } System.out.println(Thread.currentThread().getName()+" "+num); } }