本文共 10044 字,大约阅读时间需要 33 分钟。
1.Final修饰不可变的类,如String,Integer2.枚举类,enum,可反编译查看(使用javac编译后,在使用jad查看class文件为final修饰的 2.命令: a.编译-> javac ThreadSafeEnum.java b. 反编译-> jad ThreadSafeEnum.class3.final修饰的类和属性 a.创建对象时,使用final关键字能够使得另一个线程不会被访问到处于”部分创建”的对象,否则非final类在”部分创建”状态下被访问,是会可能发生类的泄漏 b.final只保证值不会被直接覆盖(如final 修饰list变量,无法直接赋值,可以通过add(e)方法添加元素)
a.线程安全类的任意方法操作都不会使该对象的数据处于不一致或者数据污染的情况,b.如java并发库下的ConcurrentHashMap,LinkedBlockingQueue
1.add方法public synchronized boolean add(E e){modCount++;ensureCapacityHelper(minCapacity:element + 1);elementData[elementCount++] = e;return true;}2.removeAllElements方法public synchronized void removeAllElements(){modCount++;//元素置为null,让gc进行资源回收for(int i = 0;ivector,Object value){ If(! vector.contains(value)){ Vector.add(value); }}
变量在多线程下会被访问和修改Public static int totalTickets = 100;Thread A : totalTickets--Thread B : totalTickets-
//固定线程数为1的线程池ExecutorService executorService = Executor.newFixedThreadPool(nThread:1);Futuresubmit = executorService.submit(new Callable (){@overridepublic String call() throws Exception{System.out.println(“正在执行。。。。。,然后通过Future异步获取任务执行结果”);return “success”;}});System.out.println(“正在做主线程的事情。。。。”);//通过Future获取异步任务执行的结果String result = submit.get();System.out.println(“拿到结果: ”+result);
1.优点: A.实时对结果处理,上下文始终在同一个代码块中,代码处理更加直观。 B.对错误和异常可以实时处理2.劣势: A.耗时的接口印象整个流程的并发量
1.优点 A.不影响主流程执行,降低响应的时间,提供应用并发量和处理能力 B.及时释放系统资源,如线程占用,内存,让系统有资源做其他事情2.缺点 A.为保证数据最终一致性,需要对账系统去做好监控和保障 B.需要更多异步任务补偿系统间的数据一致性
int port = 8080;ServerSocket server = new ServerSocket(port)//accept方法一直处于挂起状态,只有接收到相应的事件,才进行处理Socket socket = server.accept();
Socket socket = new Socket(host:”localhost”,port:8080);BufferedWrite bwriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));String str = “hello”;//bwriter 写操作时异步,不阻塞当前线程,直接写入socketChannel,不管是否写入成功Bwriter.write(str);
当前线程是激活的。关注点是:接口拿到结果方式同步实现是实时返回结果,异步是通过共享变量、通知消息或回调来得到结果
关注点:程序在等待调用结果返回时的状态
//单线程下,代码从上往下串行执行public static void main(){int start = 1;int end = 100;int sum1 = count(start,end);System.out.println(“sum1= ”+sum1);int sum2 = count2(start,end);System.out.println(“sum2 = ”+sum2 ); } public static int count(int start,int end){ int sum = 0; for (int i = start;i<= end; i++){ Sum += i; }return sum; } public static int count2(int start,int end){ return (start + end)*(end - start+1) /2; }
//多线程下,代码不按顺序地并发执行//通过线程池启动多个线程来并发执行public static void main(){ int start = 1; int end = 100; ExecutorService executorService = Executors.newFixedThreadPool(nThread:2); //通过submit或execute方法将任务提交到线程池 //线程池 分配空闲的线程执行任务 executorService.execute(()->{ int sum1=count(start,end); System.out.println(“sum1 = ”+sum1);}); executorService.execute(()->{ int sum2=count2(start,end); System.out.println(“sum2 = ”+sum2);}); }public static int count(int start,int end){int sum = 0;for (int i = start;i<= end; i++){Sum += i;}return sum;} public static int count2(int start,int end){return (start + end)*(end - start+1) /2;}
物理或实际的同时处理(多核CPU),能在同一个时刻(时间点)处理多个事件
并行具有并发的含义,但并发不一定包含并行,因为并发有可能不是同时进行
如下,3个处理器处理20个事件,则有3个事件同时进行,其他事件在进行并发处理
典型,两对列共享咖啡机。一个咖啡机(单核CPU)进行并发处理两个队列的购买请求两个咖啡机(多核CPU)并行处理两对列的购买请求
并行发具有并发含义,并发不一定是并行- 多核CPU能力强于单核CPU处理能力,且有更少系统调度和线程上下文切换
pulbic class ThreadYield{public static Object object = new Object();public static void main(String[] args){newThread(threadName:”ThreadA”).start();newThread(threadName:”ThreadB”).start();System.in.read(); }//创建、返回新的线程对象private static Thread newThread(String threadName){//返回新创建的带有代码逻辑的线程对象return new Thread(()->{for(int i = 0;i<20;i++){System.out.println(Thread.currentThread().getName()+”:”+i);//循环第十次,当前线程出让当前CPU时间片if(i == 10){Thread.yield();}} },threadName);}}
pulbic class ThreadSleep{public static Object object = new Object();public static void main(String[] args){newThread(threadName:”ThreadA”).start();newThread(threadName:”ThreadB”).start(); } //创建、返回新的线程对象private static Thread newThread(String threadName){//返回新创建的带有代码逻辑的线程对象return new Thread(()->{synchronized(object){ for(int i = 0;i<20;i++){ System.out.println(Thread.currentThread().getName()+”:”+i); if(i==10){ try{ //如是第十轮循环,则进入调用Thread.sleep()睡眠,但睡眠时,线程不释放锁 System.out.println(Thread.currentThread().getName()+”start to sleep”); //当前线程睡眠,释放CPU时间片,等到指定时间(1000MS=1s)后返回,期间不释放锁 Thread.sleep(millis:1000L); System.out.println(Thread.currentThread().getName()+”finished sleeping”); } catch(InterruptedException e){ e.printStackTrace(); } } } } },threadName);}}
pulbic class ThreadJoin{public static Object object = new Object();public static void main(String[] args){ Thread threadA = newThread(threadName:”ThreadA”)); Thread threadB = newThread(threadName:”ThreadB”); threadA.start(); threadB.start(); //hreadA调用join(),需要等待join方法执行完毕,才能执行主线程后续代码逻辑 threadA.join(); System.out.println(”等待ThreadA执行完毕/终止后,才能执行后续逻辑” ); //hreadB调用join(),需要等待join方法执行完毕,才能执行主线程后续代码逻辑 threadB.join(); System.out.println(”等待threadB执行完毕/终止后,才能执行后续逻辑” ); } //创建、返回新的线程对象private static Thread newThread(String threadName){ //返回新创建的带有代码逻辑的线程对象 return new Thread(()-> {for(int i = 0; i<5; i++){ System.out.println(Thread.currentThread().getName()+”:”+i); //循环第2次,当前线程出让当前CPU时间片 if(i == 2){ Try{Thread.sleep(millis:1000L);} catch(InterruptedException e){e.printStackTrace(); } } } },threadName); } }
pulbic class ThreadJoin{public static Object lock= new Object();public static void main(String[] args){ newThread(threadName:”ThreadA”)).start(); newThread(threadName:”ThreadB”).start(); System.in.read();} //创建、返回新的线程对象 private static Thread newThread(String threadName){ //返回新创建的带有代码逻辑的线程对象 return new Thread(()->{ //对lock对象加锁,进行同步访问 synchronized(lock){ for(int i = 0; i<5; i++){ //通知、唤醒其他所有线程去竞争对象锁Lock.notifyAll(); System.out.println(Thread.currentThread().getName()+”:”+i); try{ System.out.println(Thread.currentThread().getName()+”wait startting”); Thread.sleep(millis:1000L); System.out.println(Thread.currentThread().getName()+”wait stopped”); } catch( InterruptedException e){e.printStackTrace(); } } } },threadName);}}
pulbic class ThreadJoin{public static Object lock1= new Object();public static Object lock2= new Object();public static void main(String[] args){ //线程A获取两把锁的顺序是先获取lock1,在获取lock2 newThread(”ThreadA”,lock1,lock2)).start(); //线程B获取两把锁的顺序是先获取lock2,在获取lock1 newThread(“ThreadB”,lock2,lock1).start(); //# 由于两线程获取锁的顺序不一致,导致在获取第二把锁时,相互等待对方锁的释放,造成阻塞,产生死锁 System.in.read(); }private static Thread newThread(String threadName,Object lockFirst,Object lockSecond){return new Thread(()->{ //当前对象获取第一把锁 synchronized(lockFirst){ System.out.println(Thread.currentThread().getName()+” holding LockFirst”); try{ Thread.sleep(millis:3000L); }catch(InterruptedException e){ e.printStackTrace(); } } System.out.println(Thread.currentThread().getName()+” waiting lockSecond”); //当前对象获取第二把锁 synchronized(lockSecond){ System.out.println(Thread.currentThread().getName()+” holding lockSecond”); }},threadName);}}
转载地址:http://dhjzb.baihongyu.com/