首页
统计
关于
Search
1
Sealos3.0离线部署K8s集群
1,079 阅读
2
类的加载
739 阅读
3
Spring Cloud OAuth2.0
725 阅读
4
SpringBoot自动装配原理
690 阅读
5
集合不安全问题
583 阅读
笔记
Java
多线程
注解和反射
JVM
JUC
设计模式
Mybatis
Spring
SpringMVC
SpringBoot
MyBatis-Plus
Elastic Search
微服务
Dubbo
Zookeeper
SpringCloud
Nacos
Sentinel
数据库
MySQL
Oracle
PostgreSQL
Redis
MongoDB
工作流
Activiti7
Camunda
消息队列
RabbitMQ
前端
HTML5
CSS
CSS3
JavaScript
jQuery
Vue2
Vue3
Linux
容器
Docker
Kubernetes
Python
登录
Search
标签搜索
Java
CSS
mysql
RabbitMQ
JavaScript
Redis
JVM
Mybatis-Plus
Camunda
多线程
CSS3
Python
Spring Cloud
注解和反射
Activiti
工作流
SpringBoot
Mybatis
Spring
html5
蘇阿細
累计撰写
388
篇文章
累计收到
4
条评论
首页
栏目
笔记
Java
多线程
注解和反射
JVM
JUC
设计模式
Mybatis
Spring
SpringMVC
SpringBoot
MyBatis-Plus
Elastic Search
微服务
Dubbo
Zookeeper
SpringCloud
Nacos
Sentinel
数据库
MySQL
Oracle
PostgreSQL
Redis
MongoDB
工作流
Activiti7
Camunda
消息队列
RabbitMQ
前端
HTML5
CSS
CSS3
JavaScript
jQuery
Vue2
Vue3
Linux
容器
Docker
Kubernetes
Python
页面
统计
关于
搜索到
21
篇与
的结果
2021-02-12
Callable()
Callable()可以有返回值,可以抛出异常Callable通过Runnable接口的实现类FetuerTask调用线程package com.sw.callable; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.FutureTask; /** * @Author suaxi * @Date 2021/2/12 21:24 */ public class callableTest { public static void main(String[] args) throws ExecutionException, InterruptedException { MyThread thread = new MyThread(); FutureTask futureTask = new FutureTask(thread); //适配类 new Thread(futureTask,"A").start(); new Thread(futureTask,"B").start(); /* call()方法测试 泛型的参数 = 方法的返回值 相同的两个线程运行后只返回一个结果(有缓存) */ Object o = futureTask.get(); //获取callable返回值,此处的get可能会产生阻塞,接收返回值时可能需要等待 System.out.println(o); } } class MyThread implements Callable<String>{ @Override public String call(){ System.out.println("call()方法测试"); return "泛型的参数 = 方法的返回值"; } }
2021年02月12日
90 阅读
0 评论
0 点赞
2021-01-06
集合不安全问题
集合类不安全List不安全package com.sw.unsafe; import java.util.*; import java.util.concurrent.CopyOnWriteArrayList; /** * @Author suaxi * @Date 2021/1/4 17:12 * java.util.ConcurrentModificationException 并发修改异常 */ public class ListTest { public static void main(String[] args) { /* 并发情况下ArrayList不安全 解决方案: 1、List<String> list = new Vector<>(); 2、List<String> list = Collections.synchronizedList(new ArrayList<>()); 3、List<String> list = new CopyOnWriteArrayList<>(); CopyOnWrite 写入时复制(是一种优化策略) 多个线程调用的时候可能存在写入覆盖问题,读取没问题 CopyOnWrite在写入的时候复制一份给调用者,调用者写入新的数据完成之 后再把之前复制的数据放回原来的位置,保证线程的安全,以此避免了写入覆盖问题 相较于Vector,它没有采用synchronized锁,而是采用Lock锁,效率更高 */ List<String> list = new CopyOnWriteArrayList<>(); for (int i = 0; i < 100; i++) { new Thread(() ->{ list.add(UUID.randomUUID().toString().substring(0,5)); System.out.println(list); },String.valueOf(i)).start(); } } } Set不安全package com.sw.unsafe; import java.util.*; import java.util.concurrent.CopyOnWriteArraySet; /** * @Author suaxi * @Date 2021/1/4 22:08 * java.util.ConcurrentModificationException 并发修改异常 * 解决方法: * 1、Set<String> set = Collections.synchronizedSet(new HashSet<>()); * 2、Set<String> set = new CopyOnWriteArraySet<>(); */ public class SetTest { public static void main(String[] args) { Set<String> set = new CopyOnWriteArraySet<>(); for (int i = 0; i < 30; i++) { new Thread(() ->{ set.add(UUID.randomUUID().toString().substring(0,5)); System.out.println(set); },String.valueOf(i)).start(); } } } hashSet底层是什么?public HashSet(){ map = new HashMap<>(); } //源码 //set add的本质就是map public boolean add(E e) { return map.put(e, PRESENT)==null; } //PRESENT是静态终类 private static final Object PRESENT = new Object();Map不安全package com.sw.unsafe; import java.util.HashMap; import java.util.Map; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; /** * @Author suaxi * @Date 2021/1/4 22:26 * java.util.ConcurrentModificationException * 解决方法: * Map<String, String> map = new ConcurrentHashMap<>(); */ public class MapTest { public static void main(String[] args) { //默认等价于? new HashMap<>(16,0.75); Map<String, String> map = new ConcurrentHashMap<>(); for (int i = 0; i < 30; i++) { new Thread(() ->{ map.put(Thread.currentThread().getName(),UUID.randomUUID().toString().substring(0,5)); System.out.println(map); },String.valueOf(i)).start(); } } }
2021年01月06日
583 阅读
0 评论
0 点赞
2021-01-06
8锁问题
8锁问题什么是锁?锁的对象是谁?package com.sw.lock8; import java.util.concurrent.TimeUnit; /** * @Author suaxi * @Date 2021/1/4 15:44 * 1、执行顺序:发短信 打电话 * 2、增加睡眠时间后,执行顺序:发短信 打电话 */ public class Test1 { public static void main(String[] args) { Phone1 phone1 = new Phone1(); new Thread(() ->{ phone1.sms(); },"A").start(); try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } new Thread(() ->{ phone1.call(); },"B").start(); } } class Phone1{ //synchronized锁的对象是方法的调用者 //两个方法用的是同一个锁,谁先拿到锁,谁先调用 public synchronized void sms(){ try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("发短信"); } public synchronized void call(){ System.out.println("打电话"); } }package com.sw.lock8; import java.util.concurrent.TimeUnit; /** * @Author suaxi * @Date 2021/1/4 15:51 * 3、增加一个hello的普通方法后,执行顺序为 hello 发短信 * 4、两个对象、两个同步方式,执行顺序为 打电话 发短信 */ public class Test2 { public static void main(String[] args) { //两个对象、两个调用者、两把锁 Phone2 phone1 = new Phone2(); Phone2 phone2 = new Phone2(); new Thread(() ->{ phone1.sms(); },"A").start(); try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } new Thread(() ->{ phone2.call(); },"B").start(); } } class Phone2{ //synchronized锁的对象是方法的调用者 public synchronized void sms(){ try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("发短信"); } public synchronized void call(){ System.out.println("打电话"); } //普通方法不受锁的限制 public void hello(){ System.out.println("hello"); } }package com.sw.lock8; import java.util.concurrent.TimeUnit; /** * @Author suaxi * @Date 2021/1/4 15:58 * 5、增加static后,执行顺序为 发短信 打电话 * 6、两个Phone对象,执行顺序依然为为 发短信 打电话 */ public class Test3 { public static void main(String[] args) { //两个对象的Class类模板只有一个,与问题5一样锁的也是Class Phone3 phone = new Phone3(); Phone3 phone1 = new Phone3(); new Thread(() ->{ phone.sms(); },"A").start(); try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } new Thread(() ->{ phone1.call(); },"B").start(); } } class Phone3{ //synchronized锁的对象是方法的调用者 //static静态方法,类一加载就有了,此处锁的是Class对象 public static synchronized void sms(){ try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("发短信"); } public static synchronized void call(){ System.out.println("打电话"); } }package com.sw.lock8; import java.util.concurrent.TimeUnit; /** * @Author suaxi * @Date 2021/1/4 16:05 * 7、1个静态同步方法,1个普通同步方法,一个对象,执行顺序 打电话 发短信 * 8、1个静态同步方法,1个普通同步方法,两个对象,执行顺序 打电话 发短信 */ public class Test4 { public static void main(String[] args) { //两个对象的Class类模板只有一个,与问题5一样锁的也是Class Phone4 phone1 = new Phone4(); Phone4 phone2 = new Phone4(); new Thread(() ->{ phone1.sms(); },"A").start(); try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } new Thread(() ->{ phone2.call(); },"B").start(); } } class Phone4{ //静态同步方法 锁的是Class类模板 public static synchronized void sms(){ try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("发短信"); } //普通同步方法 锁的是调用者,不需要再等待发短信的sleep睡眠时间,两个方法用的不是同一个锁 public synchronized void call(){ System.out.println("打电话"); } }小结一个对象,拿的是同一把锁两个对象拿的是不同的锁加了static静态方法之后,不论有几个对象,锁的只有一个Class模板普通方法不受锁的限制
2021年01月06日
90 阅读
0 评论
0 点赞
2021-01-06
生产者和消费者问题
生产者和消费者问题package com.sw.pc; /** * @Author suaxi * @Date 2021/1/4 14:25 */ public class A { public static void main(String[] args) { Data data = new Data(); new Thread(() ->{ for (int i = 0; i < 10; i++) { try { data.incr(); } catch (InterruptedException e) { e.printStackTrace(); } } },"A").start(); new Thread(() ->{ for (int i = 0; i < 10; i++) { try { data.decr(); } catch (InterruptedException e) { e.printStackTrace(); } } },"B").start(); } } class Data{ private int num = 0; //+1 public synchronized void incr() throws InterruptedException { if (num!=0){ //等待 this.wait(); } num++; System.out.println(Thread.currentThread().getName()+"===>"+num); //通知 this.notifyAll(); } //-1 public synchronized void decr() throws InterruptedException { if (num==0){ //等待 this.wait(); } num--; System.out.println(Thread.currentThread().getName()+"===>"+num); //通知 this.notifyAll(); } } 当增加多个线程时(A,B,C,D),会出现虚假唤醒的问题虚假唤醒:线程可以被唤醒,但不会被通知、中断或超时解决方法:将if判断换为whilepackage com.sw.pc; /** * @Author suaxi * @Date 2021/1/4 14:25 */ public class A { public static void main(String[] args) { Data data = new Data(); new Thread(() ->{ for (int i = 0; i < 10; i++) { try { data.incr(); } catch (InterruptedException e) { e.printStackTrace(); } } },"A").start(); new Thread(() ->{ for (int i = 0; i < 10; i++) { try { data.decr(); } catch (InterruptedException e) { e.printStackTrace(); } } },"B").start(); new Thread(() ->{ for (int i = 0; i < 10; i++) { try { data.incr(); } catch (InterruptedException e) { e.printStackTrace(); } } },"C").start(); new Thread(() ->{ for (int i = 0; i < 10; i++) { try { data.decr(); } catch (InterruptedException e) { e.printStackTrace(); } } },"D").start(); } } class Data{ private int num = 0; //+1 public synchronized void incr() throws InterruptedException { while (num!=0){ //等待 this.wait(); } num++; System.out.println(Thread.currentThread().getName()+"===>"+num); //通知 this.notifyAll(); } //-1 public synchronized void decr() throws InterruptedException { while (num==0){ //等待 this.wait(); } num--; System.out.println(Thread.currentThread().getName()+"===>"+num); //通知 this.notifyAll(); } } JUC版生产者消费者问题使用了Condition接口下的await()等待和signalAll()通知package com.sw.pc; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; /** * @Author suaxi * @Date 2021/1/4 14:55 */ public class B { public static void main(String[] args) { Data1 data1 = new Data1(); new Thread(() ->{ for (int i = 0; i < 10; i++) { try { data1.incr(); } catch (InterruptedException e) { e.printStackTrace(); } } },"A").start(); new Thread(() ->{ for (int i = 0; i < 10; i++) { try { data1.decr(); } catch (InterruptedException e) { e.printStackTrace(); } } },"B").start(); new Thread(() ->{ for (int i = 0; i < 10; i++) { try { data1.incr(); } catch (InterruptedException e) { e.printStackTrace(); } } },"C").start(); new Thread(() ->{ for (int i = 0; i < 10; i++) { try { data1.decr(); } catch (InterruptedException e) { e.printStackTrace(); } } },"D").start(); } } class Data1{ private int num = 0; Lock lock = new ReentrantLock(); Condition condition = lock.newCondition(); //+1 public void incr() throws InterruptedException { try { lock.lock(); //加锁 while (num!=0){ //等待 condition.await(); } num++; System.out.println(Thread.currentThread().getName()+"===>"+num); //通知 condition.signalAll(); } catch (Exception e) { e.printStackTrace(); } finally { lock.unlock(); //解锁 } } //-1 public void decr() throws InterruptedException { try { lock.lock(); //加锁 while (num==0){ //等待 condition.await(); } num--; System.out.println(Thread.currentThread().getName()+"===>"+num); //通知 condition.signalAll(); } catch (Exception e) { e.printStackTrace(); } finally { lock.unlock(); //解锁 } } }Condition精准通知与线程唤醒可以看到之前的线程执行顺序是无序的。package com.sw.pc; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; /** * @Author suaxi * @Date 2021/1/4 15:08 * Condition精准通知与线程唤醒 * ABC三个人互相打电话,A->B,B->C,C->A顺序执行 */ public class C { public static void main(String[] args) { Data2 data2 = new Data2(); new Thread(() ->{ for (int i = 0; i < 10; i++) { data2.CallA(); } },"A").start(); new Thread(() ->{ for (int i = 0; i < 10; i++) { data2.CallB(); } },"B").start(); new Thread(() ->{ for (int i = 0; i < 10; i++) { data2.CallC(); } },"C").start(); } } class Data2{ private int num = 1; // 1A 2B 3C private Lock lock = new ReentrantLock(); Condition condition1 = lock.newCondition(); Condition condition2 = lock.newCondition(); Condition condition3 = lock.newCondition(); public void CallA(){ try { lock.lock(); //加锁 while (num!=1){ //等待 condition1.await(); } num = 2; System.out.println(Thread.currentThread().getName()+"===>A打完了"); //通知 condition2.signal(); } catch (Exception e) { e.printStackTrace(); } finally { lock.unlock(); //解锁 } } public void CallB(){ try { lock.lock(); //加锁 while (num!=2){ //等待 condition2.await(); } num = 3; System.out.println(Thread.currentThread().getName()+"===>B打完了"); //通知 condition3.signal(); } catch (Exception e) { e.printStackTrace(); } finally { lock.unlock(); //解锁 } } public void CallC(){ try { lock.lock(); //加锁 while (num!=3){ //等待 condition3.await(); } num = 1; System.out.println(Thread.currentThread().getName()+"===>C打完了"); //通知 condition1.signal(); } catch (Exception e) { e.printStackTrace(); } finally { lock.unlock(); //解锁 } } } 通过不同的监视器监视线程来达到精准通知与线程唤醒的目的
2021年01月06日
145 阅读
0 评论
0 点赞
2021-01-06
Lock锁
Lock锁传统synchronized锁package com.sw; /** * @Author suaxi * @Date 2021/1/4 14:00 */ public class SaleTicket01 { public static void main(String[] args) { Ticket1 ticket1 = new Ticket1(); new Thread(() ->{for (int i = 0; i < 30; i++) ticket1.sale();},"A").start(); new Thread(() ->{for (int i = 0; i < 30; i++) ticket1.sale();},"B").start(); new Thread(() ->{for (int i = 0; i < 30; i++) ticket1.sale();},"C").start(); } } //synchronized锁 class Ticket1{ private int num = 30; public synchronized void sale(){ if (num>0){ System.out.println(Thread.currentThread().getName()+"卖了"+(num--)+"张票,剩余:"+num); } } } Lock接口公平锁:先来后到非公平锁:可以插队(默认使用)package com.sw; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; /** * @Author suaxi * @Date 2021/1/4 11:28 */ public class SaleTicket02 { public static void main(String[] args) { Ticket ticket = new Ticket(); new Thread(() ->{for (int i = 0; i < 30; i++) ticket.sale();},"A").start(); new Thread(() ->{for (int i = 0; i < 30; i++) ticket.sale();},"B").start(); new Thread(() ->{for (int i = 0; i < 30; i++) ticket.sale();},"C").start(); } } //Lock锁 class Ticket{ private int num = 30; //1.新建重入锁 Lock lock = new ReentrantLock(); public void sale(){ lock.lock(); //2.加锁 try{ //业务代码 if (num>0){ System.out.println(Thread.currentThread().getName()+"卖了"+(num--)+"张票,剩余:"+num); } }catch (Exception e){ e.printStackTrace(); }finally { lock.unlock(); //3.解锁 } } } synchronized与Lock的区别1、synchronized 是内置的Java关键字;Lock是一个Java类2、synchronized 无法判断 获取锁 的状态;Lock可以判断3、synchronized 会自动释放锁;Lock必须手动释放,如果不释放,会产生死锁问题4、synchronized 线程1(获得锁,阻塞),线程2(一直傻傻的等待);Lock锁就不一定会一直等待下去lock.trylock()5、synchronized 可重入锁,不可中断,非公平;Lock 可重入锁,可以判断锁的状态,非公平(可自定义公平性)6、synchronized 适用于锁少量的同步代码问题;Lock 适合大量同步代码问题
2021年01月06日
66 阅读
0 评论
0 点赞
1
2
3