当前位置: 首页 > wzjs >正文

那个网站报道过鸟巢建设建手机版网站

那个网站报道过鸟巢建设,建手机版网站,免费注册公司邮箱,wordpress ftp备份Callable interface // 也是一种创建线程的方式 // Runable 能表示一个任务 (run 方法), 返回值 void ; Callable 也能表示一个任务 (call 方法), 返回值是一个具体的值, 类型可以通过泛型参数来指定 (Object) // 如果进行多线程操作, 且只关心多线程执行的过程 (像 线程池…

Callable interface 

// 也是一种创建线程的方式

// Runable 能表示一个任务 (run 方法), 返回值 void ; Callable 也能表示一个任务 (call 方法), 返回值是一个具体的值, 类型可以通过泛型参数来指定 (Object)

// 如果进行多线程操作, 且只关心多线程执行的过程 (像 线程池, 定时器等), 使用 Runable 即可; 如果是关心多线程的计算结果, 使用 Callable 更合适

// 使用 Callable 不能直接作为 Thread 的构造方法参数, 需要用 FutureTask 过渡一下

// 代码实现

public static void main(String[] args) throws ExecutionException, InterruptedException {Callable<Integer> callable = new Callable<Integer>() {@Overridepublic Integer call() throws Exception {int sum = 0;for (int i = 0; i < 1000; i++) {sum += i;}return sum;}};FutureTask<Integer> futureTask = new FutureTask<>(callable);Thread t = new Thread(futureTask);t.start();Integer result = futureTask.get();System.out.println(result);}

// get 类似于 join, 如果 call 方法没执行完, 会阻塞等待

ReentrantLock (可重入锁)

// reentrant : 可重入的

// 这个锁没有 synchronized 那么常用, 但是也是一个可选的加锁组件, 这个锁在使用上更接近于 C++ 里的锁

1. lock() 加锁

2. unlock() 解锁

// 因为是两步锁, 那么就容易出现 unlock 调用不到的情况, 比如 中间 return 了或者 抛出异常了

// unlock 容易遗漏, 所以用 finally 来执行 unlock

3.ReentrantLock 具有一些 synchronized 不具备的功能(优势)

3.1. 提供了一个 tryLock 方法进行加锁,对于 lock 操作, 如果加锁不成功就会阻塞等待 (死等), 对于 tryLock, 如果加锁失败, 直接返回 false 或可以设定等待时间, 这样就给加锁操作提供了更多的可操作空间

3.2. ReentrantLock 有两种模式, 可以工作在公平锁状态下, 也可以工作在非公平锁的状态下. 构造方法中通过参数设定的 公平/非公平 模式

3.3. ReentrantLock 也有等待通知机制, 搭配 Condition 这样的类来完成, 这里的等待通知要比 wait notify 功能更强

// synchronized 锁对象是任意对象, ReentrantLock 锁对象就是自己本身, 如果你对多个线程针对不同的 ReentrantLock 调用 lock 方法, 此时不会产生锁竞争的.

// 实际开发中, 进行多线程开发, 用到的锁依旧首选 synchronized

原子类的应用场景有哪些 

// 可以使线程既不需要加锁又可以保证线程安全

1. 计数需求

// 例如 : 视频播放中的一些数据 (播放量, 点赞量, 转发量等等)

2. 统计效果

// 统计出现错误的请求数目,请求总数(衡量服务器的压力)或每个请求的响应时间 -> 平均响应时间, (衡量服务器的运行效率), 使用原子类, 记录出错的请求数目, 另外写一个监控服务器, 获取到线上服务器的错误计数, 再通过曲线图绘制到页面上, 我们就可以及时发现 版本BUG

// 线上服务器通过这些统计内容, 进行简单计数 => 实现监控服务器, 获取/ 统计/ 展示/ 报警

信号量 Semaphore

// 在操作系统中, 也经常出现, Semaphore 是并发编程中的一个重要的概念/ 组件; 准确来说, Semaphore 是一个计数器 (变量), 描述了 "可用资源的个数", 描述的是当前线程是否"有临界资源可以用"

//临界资源: 多个线程/ 进程等并发执行的实体可以公共使用到的资源

// P / V 操作: P 操作是计数器减少(申请资源 acquire), V 操作是计数器增加(释放资源 release)

// 当计数器数值为 0 的时候, 继续 P 操作, 就会阻塞等待, 一直等待到其他线程执行了 V 操作, 释放了一个空闲资源为止

// 锁, 本质上是一种特殊的信号量 (里面的值, 非 0 即 1, 二元信号量)

// 信号量比锁更广义, 不仅仅可以描述一个资源, 还可以描述 N 个资源, 虽然概念上更广泛, 但是实际开发中还是锁更多一些 (二元信号量是最常用的)

// 伪代码 展示一下 P / V 操作

 public static void main(String[] args) throws InterruptedException {Semaphore semaphore = new Semaphore(4);semaphore.acquire();System.out.println("执行 P 操作");semaphore.release();System.out.println("执行 V 操作");}

CountDownLatch

// 针对特定场景一个组件, 当我们需要将一个任务拆分成多个部分, 每个部分用线程分别执行的时候就可以使用这个组件, 来判定出当前是否所有的任务都执行完了

// 主要用于下载方面

// 伪代码展示一下

public static void main(String[] args) throws InterruptedException {CountDownLatch countDownLatch = new CountDownLatch(10);for (int i = 0; i < 10; i++) {int id = i;Thread t = new Thread(() -> {System.out.println("线程" + id + "正在工作");try {Thread.sleep(2000);} catch (InterruptedException e) {throw new RuntimeException(e);}System.out.println("线程" + id + "结束工作");countDownLatch.countDown();});t.start();}countDownLatch.await();System.out.println("这个线程的所有任务都执行完了");}

线程安全的集合类

 // 集合类哪些是线程安全的

// Vector, Stack, HashTable 是线程安全的, 但不建议用, 其他的集合类不是线程安全的,  关键方法中, 使用 synchronized 

// Vector / HashTable 这样的集合类, 虽然加了 synchronized 也不能保证一定是线程安全的, 同时, 在单线程的情况下, 又可能因为 synchronized 影响到执行效率

1. 多线程环境使用 ArrayList

1.1 自己使用同步机制 (synchronized 或者 ReentrantLock)

1.2 Collections.synchronizedList(new ArrayList);

// ArrayList 本身没有使用 synchronized 但是你又不想自己加锁, 那么就可以使用上面这个

// 相当于让 ArrayList 像 Vector 一样工作

1.3 使用 CopyOnWriteArrayList (写时复制)

// 多线程同时修改同一个变量

// 如果多个线程去读取, 本身不会有任何线程安全问题, 一旦有线程修改, 就会把自身复制一份, 尤其修改如果比较耗时的话, 其他线程还是从旧的数据上读取, 一旦修改成功, 使用新的 ArrayList (本质上就是引用的重新赋值, 速度极快, 并且又是原子的), 这个过程中没有引入任何的加锁操作, 使用了 创建副本 => 修改副本 => 使用副本替换, 类似于显卡渲染画面

2. 多线程使用哈希表

// HashMap 本身不是线程安全的

2.1 HashTable 是线程安全的, 关键方法都提供了 synchronized

// HashTable 是在方法上直接加上 synchronized, 就相当于针对 this 加锁

2.2 ConcurrentHashMap 是线程安全的 Hash 表

2.2.1 [核心] 减小了锁的粒度, 每个链表有一把锁, 大部分情况下都不会涉及到锁冲突

2.2.2 广泛使用 CAS 操作, 像 size++ 这种操作就不会产生锁冲突

2.2.3 写操作进行了加锁(链表级), 读操作, 不加锁了

2.2.4 针对扩容操作进行了优化, 渐进式扩容

// 化整为零, 当需要扩容的时候, 会创建出另一个更大的数组, 然后把旧的数组上的数据逐渐的往新的数组上搬运. 会出现一段时间, 旧数组和新数组同时存在

2.2.4.1 新增元素, 往新数组上插入

2.2.4.2 删除元素, 把旧数组的元素给删掉即可

2.2.4.3 查找元素, 新旧数组都要查找

2.2.4.4 修改元素, 统一把这个元素给搞到新的数组上

// 与此同时, 每个操作都会触发一定程度搬运, 每次搬运一点, 就可以保证整体的时间不是很长, 积少成多之后, 逐渐完成搬运了, 也就可以把之前的旧数组彻底销毁了

// HashMap 和 ConcurrentHashMap 之间的区别在于: 线程不安全和线程安全之间的区别

// Java 8 之前, ConcurrentHashMap 是使用分段锁, 之后都是每个链表一把锁

创建新线程的几种方式

1. 直接继承 Thread 

2. 实现 Runable 

3. 使用 lambda

4. 使用线程池

// 线程池构造方法中的 ThreadFactory 也可以构造线程

5. 使用 Callable 

// 其中 1, 2, 5 这三种方法又可以搭配匿名内部类来使用 

http://www.dtcms.com/wzjs/560840.html

相关文章:

  • 全国做网站找哪家好邯郸做网站价格
  • 整站优化推广品牌wordpress一定要本地建站吗
  • 集团高端网站建设平面设计类的网站
  • 青岛高端网站开发驻马店北京网站建设
  • 网站首页 模板网站百科怎么做
  • 老专家个人网站廊坊网站建设企业
  • 免费网站服务器安全百度seo提交
  • 企业简介的网站怎么做百度ip地址
  • 南昌购物网站开发网站建设模块方案书
  • 网络营销网站源码怎么把一个网站设置成首页
  • asp.net做网站next 主题wordpress
  • 贵州seo技术查询台州网站优化公司
  • 中山网站建设联系电话广点通都有哪些平台投放
  • 网站收录软件表格里怎么做链接网站
  • 聊城那里有做网站网站服务器租用 配置
  • 网站广告位制作权威发布型舆情回应以事实性
  • 多语言外贸企业网站源码wordpress 自动标签插件
  • 深圳做高端网站建设公司郑州网站开发网站开发
  • 网站页面在线设计虎扑体育网体育
  • photoshop做网站设计浏览器兄弟懂的拿走不谢2021
  • 网站建设的上市公司c 可以做网站吗
  • 漳州网站优化东莞气缸东莞网站建设
  • 智能建网站wordpress 机械模板下载地址
  • 免费不收费用网站网站公众号小程序开发公司
  • 南宁网站建设招聘禁止显示网站目录
  • 辽源做网站公司seo插件wordpress
  • 怎么做免费的网站商城wap网站制作
  • 黄石网站设计公司哪些购物网站做的比较简洁有品质
  • 临沂城乡建设管理局网站哪个网站是可以做书的
  • 研究网站平台建设工作动态装修工人自己接单的app