Java中的线程--线程中的工具
这主要想写一下Java中的jdk提供的一些线程中的工具,
一、semaphore信号灯
Semaphore可以维护当前访问自身的线程个数,并提供了同步机制,使用Semaphore可以控制同时访问资源的线程的个数。例如,实现一个文件允许访问的并发数。
Semaphore实现的功能就类似厕所5个坑,假如有10个人要上厕所,那么同时可以有多少人上厕所呢?同时只能有5个人能够占用,当5个人中的任何一个让开后,其中在等待的另外5个中的一个就可以占用了。
单个信号量的Semaphore对象可以实现互斥锁的功能,并且可以是由一个线程获得了“锁”,再由另一个线程释放“锁”,这可应用于死锁恢复的一些场合。
代码如下:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore; /**
* @className: SemaphoreTest
* @description: Semaphore信号灯测试实例
* @author: ssc
* @date: 2019年6月18日 下午9:01:33
*/
public class SemaphoreTest { public static void main(String[] args) { ExecutorService services = Executors.newCachedThreadPool();
Semaphore sp = new Semaphore(3); for (int i = 0; i < 10; i++) {
Runnable runnable = new Runnable() {
@Override
public void run() {
try {
// 查询信号灯的状态 是否可以进入
sp.acquire();
System.out.println("线程 " + Thread.currentThread().getName() + "进入,当前已有"
+ (3 - sp.availablePermits()) + " 并发");
Thread.sleep((long) (Math.random() * 10000));
System.out.println("线程 " + Thread.currentThread().getName() + " 即将离开");
// 释放信号灯 让别的线程进入
sp.release();
System.out.println("线程 " + Thread.currentThread().getName() + "已离开,当前已有"
+ (3 - sp.availablePermits()) + " 并发");
} catch (Exception e) {
e.printStackTrace();
}
}
};
services.execute(runnable);
}
} }
二、CyclicBarrier循环路障
字面意思回环栅栏,通过它可以实现让一组线程等待至某个状态之后再全部同时执行。叫做回环是因为当所有等待线程都被释放以后,CyclicBarrier可以被重用。我们暂且把这个状态就叫做barrier,当调用await()方法之后,线程就处于barrier了。
使用代码如下:
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; /**
* @className: CyclicBarrier
* @description: 线程中的循环路障工具类
* @author: ssc
* @date: 2019年6月18日 下午9:58:36
*/
public class CyclicBarrierTest { public static void main(String[] args) {
ExecutorService services = Executors.newCachedThreadPool();
// 创建 路障实例对象
CyclicBarrier cb = new CyclicBarrier(3); for (int i = 0; i < 3; i++) {
Runnable runnable = new Runnable() {
@Override
public void run() {
try { Thread.sleep((long) Math.random() * 10000);
System.out.println("线程 " + Thread.currentThread().getName() + "即将到达集合地点1,当前已有"
+ (cb.getNumberWaiting()) + " 到达,正在等候...");
// 到此如果没有达到公共屏障点,则该线程处于等待状态,如果达到公共屏障点则所有处于等待的线程都继续往下运行
cb.await(); Thread.sleep((long) Math.random() * 10000);
System.out.println("线程 " + Thread.currentThread().getName() + "即将到达集合地点2,当前已有"
+ (cb.getNumberWaiting()) + " 到达,正在等候...");
cb.await(); Thread.sleep((long) Math.random() * 10000);
System.out.println("线程 " + Thread.currentThread().getName() + "即将到达集合地点3,当前已有"
+ (cb.getNumberWaiting()) + " 都到齐了, 继续走啊!");
cb.await(); } catch (Exception e) {
e.printStackTrace();
}
}
};
services.execute(runnable);
}
services.shutdown();
} }
三、CountDownLatch倒计时计时器
CountDownLatch犹如倒计时计时器,调用CountDownLatch对象的countDown方法就将计时器减去1。当计时器到达0时,则所有等待着或者单个等待着开始执行。
可以实现一个人或者是多个人等待其他人通知他,可以实现一个人通知多个人的效果。类似裁判一声口令,运动员同时开始奔跑,或者所有运动员都跑到终点后裁判才可以通知结果。还可以实现一个计划需要多个领导签字后才可以继续向下实施的情况
示例代码如下:
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; /**
* @className: CountDownLatchTest
* @description: 线程中的计时器类
* @author: ssc
* @date: 2019年6月20日 下午9:13:40
*/
public class CountDownLatchTest { public static void main(String[] args) {
ExecutorService services = Executors.newCachedThreadPool();
// 主线程中的计时器 相当于赛跑中的裁判
CountDownLatch cdOrder = new CountDownLatch(1);
// 新建线程的计时器 相当于赛跑中的运动员
CountDownLatch cdAnswer = new CountDownLatch(3); for (int i = 0; i < 3; i++) {
Runnable runnable = new Runnable() {
@Override
public void run() {
try {
System.out.println("线程 " + Thread.currentThread().getName() + "正准备接受命令...");
// 等待计时器上技数值 归0 才开始执行 相当于运动员等待裁判的起跑枪声
cdOrder.await();
System.out.println("线程 " + Thread.currentThread().getName() + "已经接受命令...");
Thread.sleep((long) (Math.random() * 10000));
System.out.println("线程 " + Thread.currentThread().getName() + "等待命令处理结果...");
// 计时器上的数值减去1 相当于运动员相继跑到终点 等待裁判宣布最终结果
cdAnswer.countDown();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
services.execute(runnable);
}
services.shutdown(); try {
Thread.sleep((long) (Math.random() * 10000));
System.out.println("线程 " + Thread.currentThread().getName() + "即将发布命令...");
// 计数器上的 技数的值减去1 这个计数器本身就是 1 就相当于裁判的起跑枪声,只有这个计时器到0,其他线程才开始执行
cdOrder.countDown();
System.out.println("线程 " + Thread.currentThread().getName() + "已经发布命令,正在等待结果...");
// 只有另外三个线程都执行到这里,分别将计时器的数值减去1,下面的代码才执行,相当于裁判等运动员都通过终点,才宣布结果
cdAnswer.await();
System.out.println("线程 " + Thread.currentThread().getName() + "已收到所有响应结果...");
} catch (Exception e) {
e.printStackTrace();
}
}
}
四、Exchanger工具类
用于实现两个人之间的数据交换,每个人在完成一件事物后,想与对方交换数据,第一个拿出数据的人将一直等待第二个人拿出数据来时,才会互相交换
示例代码如下:
import java.util.concurrent.Exchanger;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; /**
* @className: ExchangerTest
* @description: Exchanger工具类的示例
* @author: ssc
* @date: 2019年6月20日 下午10:00:19
*/
public class ExchangerTest { public static void main(String[] args) {
ExecutorService services = Executors.newCachedThreadPool(); Exchanger exchanger = new Exchanger(); services.execute(new Runnable() {
@Override
public void run() {
try {
String data1 = "abc";
System.out.println("线程" + Thread.currentThread().getName() + "正准备把数据" + data1 + "换出去");
Thread.sleep((long) (Math.random() * 10000));
// 进行数据的交换
String data2 = (String) exchanger.exchange(data1);
System.out.println("线程" + Thread.currentThread().getName() + "换回的数据是" + data2);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}); services.execute(new Runnable() {
@Override
public void run() {
try {
String data1 = "edf";
System.out.println("线程" + Thread.currentThread().getName() + "正准备把数据" + data1 + "换出去");
Thread.sleep((long) (Math.random() * 10000));
// 进行数据的交换
String data2 = (String) exchanger.exchange(data1);
System.out.println("线程" + Thread.currentThread().getName() + "换回的数据是" + data2);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
services.shutdown();
}
}
Java中的线程--线程中的工具的更多相关文章
- Java(多)线程中注入Spring的Bean
问题说明 今天在web应用中用到了Java多线程的技术来并发处理一些业务,但在执行时一直会报NullPointerException的错误,问题定位了一下发现是线程中的Spring bean没有被注入 ...
- -1-5 java 多线程 概念 进程 线程区别联系 java创建线程方式 线程组 线程池概念 线程安全 同步 同步代码块 Lock锁 sleep()和wait()方法的区别 为什么wait(),notify(),notifyAll()等方法都定义在Object类中
本文关键词: java 多线程 概念 进程 线程区别联系 java创建线程方式 线程组 线程池概念 线程安全 同步 同步代码块 Lock锁 sleep()和wait()方法的区别 为什么wait( ...
- 【转】Java(多)线程中注入Spring的Bean
问题说明 今天在web应用中用到了Java多线程的技术来并发处理一些业务,但在执行时一直会报NullPointerException的错误,问题定位了一下发现是线程中的Spring bean没有被注入 ...
- Java线程并发中常见的锁
随着互联网的蓬勃发展,越来越多的互联网企业面临着用户量膨胀而带来的并发安全问题.本文着重介绍了在java并发中常见的几种锁机制. 1.偏向锁 偏向锁是JDK1.6提出来的一种锁优化的机制.其核心的思想 ...
- Java核心知识点学习----线程中的Semaphore学习,公共厕所排队策略
1.什么是Semaphore? A counting semaphore. Conceptually, a semaphore maintains a set of permits. Each acq ...
- Java核心知识点学习----线程中如何创建锁和使用锁 Lock,设计一个缓存系统
理论知识很枯燥,但这些都是基本功,学完可能会忘,但等用的时候,会发觉之前的学习是非常有意义的,学习线程就是这样子的. 1.如何创建锁? Lock lock = new ReentrantLock(); ...
- ThreadLocal,Java中特殊的线程绑定机制
在DRP项目中,我们使用了ThreadLocal来创建Connection连接,避免了一直以参数的形式将Connection向下传递(传递connection的目的是由于jdbc事务要求确保使用同一个 ...
- Java中的守护线程和非守护线程(转载)
<什么是守护线程,什么是非守护线程> Java有两种Thread:"守护线程Daemon"(守护线程)与"用户线程User"(非守护线程). 用户线 ...
- Java中的守护线程 & 非守护线程(简介)
Java中的守护线程 & 非守护线程 守护线程 (Daemon Thread) 非守护线程,又称用户线程(User Thread) 用个比较通俗的比如,任何一个守护线程都是整个JVM中所有非守 ...
- Java线程并发中常见的锁--自旋锁 偏向锁
随着互联网的蓬勃发展,越来越多的互联网企业面临着用户量膨胀而带来的并发安全问题.本文着重介绍了在java并发中常见的几种锁机制. 1.偏向锁 偏向锁是JDK1.6提出来的一种锁优化的机制.其核心的思想 ...
随机推荐
- 无法序列化会话状态。请注意,当会话状态模式为“StateServer”或“SQLServer”时,不允许使用无法序列化的对象或 MarshalByRef 对象。
原文链接:http://blog.csdn.net/byondocean/article/details/7564502 session是工作在你的应用程序进程中的.asp.net进程.iis往往会在 ...
- hdoj 1588 学好线代与数学
按部就班,超级简单,虽然不是一次过的...错在那个long long数据问题还是要注意..也不知道要怎么注意:还是说题目吧... 思路看main函数 其他函数功能也是非常有用!代码比较丑...见谅 # ...
- 新建Podfile命令
接下来,你需要建立一个主工程.建立成功以后,再次启动终端, 利用cd命令进入到工程文件夹内,此时需要创建一个特殊的文本文件,命令如下: 命令: touch Podfile 创建 命令: open -e ...
- 企业级应用,如何实现服务化三(dubbo入门案例)
今天是六一儿童节,从千里之外的广州,回到了贵州老家,真好!好山好水好心情,好了接着写点东西.这是企业级应用,如何实现服务化系列的第三篇.在上一篇:企业级应用,如何实现服务化二(dubbo架构)中,认识 ...
- TopJUI通过简单的代码实现复杂的批量提交功能
业务系统的批量提交是常用的操作功能,使用传统的EasyUI开发时需要写不少代码才能实现,该功能在TopJUI中是如何实现的呢?本篇我们将通过简单的代码,把批量操作的具体实现分享给大家参考. <a ...
- C 语言实例 - 输出当前文件执行代码
C 语言实例 - 输出当前文件执行代码 输出当前文件执行代码,__FILE__ 为当前执行的文件常量. 实例 #include <stdio.h> int main() { FILE *f ...
- kafka剖析(转)
Kafka是由LinkedIn开发的一个分布式的消息系统,使用Scala编写,它以可水平扩展和高吞吐率而被广泛使用.目前越来越多的开源分布式处理系统如Cloudera.Apache Storm.Spa ...
- UWP 画一个圆形头像
经常需要做一个圆形头像的样式,like this 做法很简单,直接上xaml. <Ellipse Width=" Height="> <Ellipse.Fill& ...
- Codeforces 1132G(关系转化树+dfn+线段树)
要点 显然要滑动修改维护. 像通常的数列next关系一样建边(单调栈预处理),因为贪心所以是树,然后发现增删只会影响区间内的子(or父,看你连边方向行事)节点,于是使用dfs序建线段树. 为了正确地修 ...
- 使用高性能Pipelines构建.NET通讯程序
.NET Standard支持一组新的API,System.Span, System.Memory,还有System.IO.Pipelines.这几个新的API极大了提升了.NET程序的效能,将来.N ...