<script async="" src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
<ins class="adsbygoogle" style="display:block; text-align:center;" data-ad-layout="in-article" data-ad-format="fluid" data-ad-client="ca-pub-7963911354665843" data-ad-slot="7239246954"></ins>
<script>
(adsbygoogle = window.adsbygoogle || []).push({});
</script>
<br>
<h3 id="articleHeader0">安全共享对象策略</h3>

1.线程限制 : 一个被线程限制的对象,由线程独占,并且只能被占有它的线程修改

2.共享只读 : 一个共享只读的对象,在没有额外同步的情况下,可以被多个线程并发访问,

但是任何线程都不能修改它

3.线程安全对象 : 一个线程安全的对象或则容器,在内部通过同步机制来保证线程安全,

所以其他线程无需额外的同步就可以通过公共接口随意访问它

4.被守护对象 : 被守护对象只能通过获取特定的锁来访问

线程安全 - 同步容器

采用synchronized关键字同步,缺点 :

  1. 不能完成做到线程安全
  2. 性能差

ArrayLisy -> Vector, Stack

HashMap -> HashTable (key、value不能为null)

Collections.synchronizedXXX(List、Set、Map)

线程安全 - 并发容器 J.U.C

ArrayList -> CopyOnWriteArrayList

HashSet、TreeSet -> CopyOnWriteArraySet ConcurrentSkipListSet

HashMap、TreeMap -> ConcurrentHashMap ConcurrentSkipListMap

AbstractQueuedSynchronizer - AQS

  1. 使用Node实现FIFO队列,可以用于构建锁或则其他同步装置的基础框架
  2. 利用一个int类型表示状态
  3. 使用方法是基础
  4. 子类通过继承并通过实现它的方法管理其状态 { acquire 和 release} 的方法操纵状态
  5. 可以同时实现排他锁和共享锁模式(独占、共享)

常用类

CountDownLatch

Semaphore

CyclicBarrier

ReentrantLock

Condition

FutureTask

CountDownLacth

CountDownLatch是一个同步工具类,它允许一个或多个线程一直等待,直到其他线程执行完后再执行。例如,应用程序的主线程希望在负责启动框架服务的线程已经启动所有框架服务之后执行。

CountDownLatch是通过一个计数器来实现的,计数器的初始化值为线程的数量。每当一个线程完成了自己的任务后,计数器的值就相应得减1。当计数器到达0时,表示所有的线程都已完成任务,然后在闭锁上等待的线程就可以恢复执行任务。

@Self4j
public class CountDownLatchExample { private final static int threadCount = 200; public static void main(String[] arg) { ExecutorService exec = Executors.newCachedThreadPool(); final CountDownLatch lacth = new CountDownLatch(5); for (int i = 0; i < 1000; i++) {
exec.excute( () -> {
final int threadNum = i;
try {
test(threadNum);
} catch (Exception e) {
log.error("exception", e);
} finally {
// latch递减
lacth.countDown();
}
});
}
// 等待latch计数器为0,则继续往下执行
latch.await();
// latch的await方法也可以传入等待时间,等到等待时间后不管有没完成计数都往下执行
// latch.await( 10, TimeUnit.MILLISECONDS);
log.info("finished");
exec.shutdown();
} public static void test(int i) throw Exception{
log.info("thread: {}", i);
}
}

Semaphore

Semaphore(int permits):构造方法,创建具有给定许可数的计数信号量并设置为非公平信号量。

Semaphore(int permits,boolean fair):构造方法,当fair等于true时,创建具有给定许可数的计数信号量并设置为公平信号量。

void acquire():从此信号量获取一个许可前线程将一直阻塞。

void acquire(int n):从此信号量获取给定数目许可,在提供这些许可前一直将线程阻塞。

void release():释放一个许可,将其返回给信号量。就如同车开走返回一个车位。

void release(int n):释放n个许可。

int availablePermits():获取当前可用的许可数。

boolean tryAcquire():仅在调用时此信号量存在一个可用许可,才从信号量获取许可。

boolean tryAcquire(int permits):仅在调用时此信号量中有给定数目的许可时,才从此信号量中获取这些许可。

boolean tryAcquire(int permits,
long timeout,
TimeUnit unit)
throws InterruptedException

如果在给定的等待时间内此信号量有可用的所有许可,并且当前线程未被 中断,则从此信号量获取给定数目的许可。

@Self4j
public class SemaphoreExample { private final static int threadCount = 200; public static void main(String[] arg) { ExecutorService exec = Executors.newCachedThreadPool(); final Semaphore semaphore = new Semaphore(3); for (int i = 0; i < threadCount; i++) {
exec.excute( () )-> {
final int threadNum = i;
try {
// tryAcquire会尝试去获取一个信号量,如果获取不到
// 则什么都不会发生,走接下来的逻辑
// if (semaphore.tryAcquire(1)) {
// test(i);
// semaphore.release();//释放一个信号量
// }
semaphore.acquire();//获取一个信号量
test(i);
semaphore.release();//释放一个信号量
} catch (Exception e) {
log.error("exception", e);
}
});
}
log.info("finished");
exec.shutdown();
} public static void test(int i) throw Exception{
log.info("thread: {}", i);
}
}

CyclicBarrier

一个同步辅助类,它允许一组线程互相等待,直到到达某个公共屏障点 (common barrier point)。

CyclicBarrier(int parties, Runnable barrierAction)

创建一个新的 CyclicBarrier,它将在给定数量的参与者(线程)处于等待状态时启动,并在启动 barrier 时执行给定的屏障操作,该操作由最后一个进入 barrier 的线程执行。

CyclicBarrier(int parties)

创建一个新的 CyclicBarrier,它将在给定数量的参与者(线程)处于等待状态时启动,但它不会在启动 barrier 时执行预定义的操作。

int await()

在所有 参与者都已经在此 barrier 上调用 await 方法之前,将一直等待。

int await(long timeout,
TimeUnit unit)
throws InterruptedException,
BrokenBarrierException,
TimeoutException

在所有 参与者都已经在此屏障上调用 await 方法之前将一直等待,或者超出了指定的等待时间。

boolean isBroken() : 查询此屏障是否处于损坏状态。

void reset() :

将屏障重置为其初始状态。如果所有参与者目前都在屏障处等待,则它们将返回,同时抛出一个 BrokenBarrierException。注意,在由于其他原因造成损坏 之后,实行重置可能会变得很复杂;此时需要使用其他方式重新同步线程,并选择其中一个线程来执行重置。与为后续使用创建一个新 barrier 相比,这种方法可能更好一些。

int getNumberWaiting() :返回当前在屏障处等待的参与者数目。此方法主要用于调试和断言。

@Self4j
public class CyclicBarrierExample { private final static int threadCount = 200; private final static CyclicBarrier cyclicBarrier = new CyclicBarrier(7,
() -> {
log.info("callback is running !");
}
); public static void main(String[] arg) { ExecutorService exec = Executors.newCachedThreadPool(); for (int i = 0; i < threadCount; i++) {
exec.excute( () -> {
final int threadNum = i;
try {
race(i);
} catch (Exception e) {
log.error("exception", e);
}
});
}
log.info("finished"); exec.shutdown();
} public static void race(int i) throw Exception{
log.info("thread {} is ready", i);
cyclicBarrier.await();
log.info("thread {} is continue", i);
}
}

查看原文: Java并发多线程 - 并发工具类JUC

								</article>

Java并发多线程 - 并发工具类JUC的更多相关文章

  1. Java接口多线程并发测试 (一)

    本文为作者原创,禁止转载,违者必究法律责任!!! 本文为作者原创,禁止转载,违者必究法律责任!!! Java接口多线程并发测试 一,首先写一个接口post 请求代码: import org.apach ...

  2. Java多线程同步工具类之CountDownLatch

    在过去我们实现多线程同步的代码中,往往使用join().wait().notiyAll()等线程间通信的方式,随着JUC包的不断的完善,java为我们提供了丰富同步工具类,官方也鼓励我们使用工具类来实 ...

  3. Rhino+envjs-1.2.js 在java运行网站js 工具类

    java爬虫遇到个页面加密的东西,找了些资料学习学习 做了个java运行js的工具类,希望对大家有用,其中用到client(获取js)可以自行换成自己的client.主要是用了 Rhino就是Java ...

  4. java中常用的工具类(一)

    我们java程序员在开发项目的是常常会用到一些工具类.今天我汇总了一下java中常用的工具方法.大家可以在项目中使用.可以收藏!加入IT江湖官方群:383126909 我们一起成长 一.String工 ...

  5. Java学习-041-颜色工具类(RGB,HEX)

    在日常的网页开发中,经常需要进行颜色数值获取.转换,例如获取红色,获取蓝色,获取绿色,RGB转十六进制颜色,十六进制颜色转RGB等,因而在学习过程中,写了一个小工具类,仅供各位小主参考! 多不闲言,直 ...

  6. JAVA中封装JSONUtils工具类及使用

    在JAVA中用json-lib-2.3-jdk15.jar包中提供了JSONObject和JSONArray基类,用于JSON的序列化和反序列化的操作.但是我们更习惯将其进一步封装,达到更好的重用. ...

  7. JAVA自动生成正则表达式工具类

    经过很久的努力,终于完成了JAVA自动生成正则表达式工具类.还记得之前需要正则,老是从网上找吗?找了想修改也不会修改.现在不用再为此烦恼了,使用此生成类轻松搞定所有正则表达式.赶快在同事面前炫一下吧. ...

  8. java 二进制数字符串转换工具类

    java 二进制数字符串转换工具类 将二进制转换成八进制 将二进制转换成十进制 将二进制转换成十六进制 将十进制转换成二进制 package com.iteye.injavawetrust.ad; i ...

  9. Java学习-049-正则工具类

    自去年九月份决定再次入学和职业资格进阶,开始备战二者考试至今,以及当下进行中的职称申请,犹如孤独的狼,不断前行在路上,而今凡凡总总的已历8月... 不感慨了,如下为一园友需要的正则工具类,直接上码: ...

随机推荐

  1. SpringBoot项目打包成jar后,启动脚本

    将springboot项目打包成jar后,上传至服务器,每次都需要手敲命令,重新部署项目,可将这些命令写入脚本中,直接运行. 启动脚本(start.sh): CUR_PATH=$(cd "$ ...

  2. 【转】Linux内核结构详解

    Linux内核主要由五个子系统组成:进程调度,内存管理,虚拟文件系统,网络接口,进程间通信. 1.进程调度 (SCHED):控制进程对CPU的访问.当需要选择下一个进程运行时,由调度程序选择最值得运行 ...

  3. 并查集(Union/Find)模板及详解

    概念: 并查集是一种非常精巧而实用的数据结构,它主要用于处理一些不相交集合的合并问题.一些常见的用途有求连通子图.求最小生成树的Kruskal 算法和求最近公共祖先等. 操作: 并查集的基本操作有两个 ...

  4. lintcode-151-买卖股票的最佳时机 III

    151-买卖股票的最佳时机 III 假设你有一个数组,它的第i个元素是一支给定的股票在第i天的价格.设计一个算法来找到最大的利润.你最多可以完成两笔交易. 注意事项 你不可以同时参与多笔交易(你必须在 ...

  5. iOS-开发过程中应用间跳转问题

  6. 伟大的淘宝IP库的API接口竟然提示503挂掉了

    1 淘宝IP库惊现503错误 吃完晚饭,大概6点半了,天色已暗,太阳早就落山了.回到宿舍打开博客一看,傻眼了:博客每篇文章的评论者的地理信息全部处于“正在查询中……”的状态.这神马情况,不会是被淘宝封 ...

  7. Winform 数据绑定

    1.DataGridView数据绑定 namespace WindowsFormsApplication1 { public partial class Form1 : Form { private ...

  8. [STAThread] 作用

    [STAThread]是一种线程模型,用在程序的入口方法上(在C#和VB.NET里是Main()方法),来指定当前线程的ApartmentState 是STA. [STAThread]是声明开始线程用 ...

  9. 爬虫之手机APP抓包教程-亲测HTTP和HTTPS均可实现

    当下很多网站都有做自己的APP端产品,一个优秀的爬虫工程师,必须能够绕过难爬取点而取捷径,这是皆大欢喜的.但是在网上收罗和查阅了无数文档和资料,本人亲测无数次,均不能正常获取HTTPS数据,究其原因是 ...

  10. [剑指Offer] 60.把二叉树打印成多行

    题目描述 从上到下按层打印二叉树,同一层结点从左至右输出.每一层输出一行. [思路]使用队列实现二叉树的层次遍历. /* struct TreeNode { int val; struct TreeN ...