如何在java中实现跨线程的通讯
一般而言,如果没有干预的话,线程在启动之后会一直运行到结束,但有时候我们又需要很多线程来共同完成一个任务,这就牵扯到线程间的通讯。
如何让两个线程先后执行?Thread.join方法
private static void demo2() {
Thread A = new Thread(new Runnable() {
@Override
public void run() {
printNumber("A");
}
});
Thread B = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("B starts waiting for A");
try {
A.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
printNumber("B");
}
});
B.start();
A.start();
}
其中A.join()的意思即是等待A线程执行完毕。
如何让两个线程交互执行?object.wait和object.notify方法
/**
* A 1, B 1, B 2, B 3, A 2, A 3
*/
private static void demo3() {
Object lock = new Object();
Thread A = new Thread(new Runnable() {
@Override
public void run() {
synchronized (lock) {
System.out.println("A 1");
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("A 2");
System.out.println("A 3");
}
}
});
Thread B = new Thread(new Runnable() {
@Override
public void run() {
synchronized (lock) {
System.out.println("B 1");
System.out.println("B 2");
System.out.println("B 3");
lock.notify();
}
}
});
A.start();
B.start();
}
A在输出完1之后等待B的notify才会去执行其他的操作。
如何让四个线程的其中一个等待其他三个执行完毕?CountdownLatch就是干这个的。
CountdownLatch的基本用法
- 创建一个CountdownLatch并赋初始值,
CountdownLatch countDownLatch = new CountDownLatch(3; - 在需要等待的线程中调用
countDownLatch.await()进入等待状态; - 在其他线程执行中适当的时候调用
countDownLatch.countDown(),会使内部否计数值减一; - 当
countDown()导致count值为 0, 则处于等待态的线程开始执行。
private static void runDAfterABC() {
int worker = 3;
CountDownLatch countDownLatch = new CountDownLatch(worker);
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("D is waiting for other three threads");
try {
countDownLatch.await();
System.out.println("All done, D starts working");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
for (char threadName='A'; threadName <= 'C'; threadName++) {
final String tN = String.valueOf(threadName);
new Thread(new Runnable() {
@Override
public void run() {
System.out.println(tN + "is working");
try {
Thread.sleep(100);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(tN + "finished");
countDownLatch.countDown();
}
}).start();
}
}
如何让三个线程的各自开始做一些事情,然后在某个时间点上进行同步?CyclicBarrier 是干这个的。
CyclicBarrier 的用法:
- 首先还是需要先创建一个
CyclicBarrier对象,设置初始值,CyclicBarrier cyclicBarrier = new CyclicBarrier(3); - 各个线程同步启动,在完成一些逻辑之后,调用
cyclicBarrier.await()开始等待; - 当所有的线程都调用了
cyclicBarrier.await()之后,每个线程都可以执行之后的逻辑。
private static void runABCWhenAllReady() {
int runner = 3;
CyclicBarrier cyclicBarrier = new CyclicBarrier(runner);
final Random random = new Random();
for (char runnerName='A'; runnerName <= 'C'; runnerName++) {
final String rN = String.valueOf(runnerName);
new Thread(new Runnable() {
@Override
public void run() {
long prepareTime = random.nextInt(10000) + 100;
System.out.println(rN + "is preparing for time:" + prepareTime);
try {
Thread.sleep(prepareTime);
} catch (Exception e) {
e.printStackTrace();
}
try {
System.out.println(rN + "is prepared, waiting for others");
cyclicBarrier.await(); // The current runner is ready, waiting for others to be ready
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
System.out.println(rN + "starts running"); // All the runners are ready to start running together
}
}).start();
}
}
如何取回某个线程的返回值了?Callable 是干这个的。
先看下定义:
@FunctionalInterface
public interface Callable<V> {
/**
* Computes a result, or throws an exception if unable to do so.
*
* @return computed result
* @throws Exception if unable to compute a result
*/
V call() throws Exception;
}
然后直接给个例子:
private static void doTaskWithResultInWorker() {
Callable<Integer> callable = new Callable<Integer>() {
@Override
public Integer call() throws Exception {
System.out.println("Task starts");
Thread.sleep(1000);
int result = 0;
for (int i=0; i<=100; i++) {
result += i;
}
System.out.println("Task finished and return result");
return result;
}
};
FutureTask<Integer> futureTask = new FutureTask<>(callable);
new Thread(futureTask).start();
try {
System.out.println("Before futureTask.get()");
System.out.println("Result:" + futureTask.get());
System.out.println("After futureTask.get()");
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
注意,其中futureTask.get()方法是阻塞调用。
以上都是一些很基本的应用,在新版本的CompleteFuture中其实提供了更多的链式操作,不过写起来比较复杂,看起来也不清晰。
如何在java中实现跨线程的通讯的更多相关文章
- 如何在Java中编写一个线程安全的方法?
线程安全总是与多线程有关的,即一个线程访问或维护数据时遭到了其它线程的“破坏”,为了不被破坏,就要保持所维护变量的原子性: 1 局部变量总是线程安全的,因为每个线程都有自己的栈,而在方法中声明的变量都 ...
- 用代码说话:如何在Java中实现线程
并发编程是Java语言的重要特性之一,"如何在Java中实现线程"是学习并发编程的入门知识,也是Java工程师面试必备的基础知识.本文从线程说起,然后用代码说明如何在Java中实现 ...
- 如何在Java中测试类是否是线程安全的
通过优锐课的java核心笔记中,我们可以看到关于如何在java中测试类是否线程安全的一些知识点汇总,分享给大家学习参考. 线程安全性测试与典型的单线程测试不同.为了测试一个方法是否是线程安全的,我们需 ...
- 『动善时』JMeter基础 — 38、JMeter中实现跨线程组关联
目录 1.JMeter中实现跨线程组关联说明 (1)JMeter中实现跨线程组关联步骤 (2)测试计划内包含的元件 2.用户登陆请求的相关操作 (1)进行登陆操作获取Cookie信息 (2)把Cook ...
- Java 中如何实现线程间通信
世界以痛吻我,要我报之以歌 -- 泰戈尔<飞鸟集> 虽然通常每个子线程只需要完成自己的任务,但是有时我们希望多个线程一起工作来完成一个任务,这就涉及到线程间通信. 关于线程间通信本文涉及到 ...
- 如何在JAVA中实现一个固定最大size的hashMap
如何在JAVA中实现一个固定最大size的hashMap 利用LinkedHashMap的removeEldestEntry方法,重载此方法使得这个map可以增长到最大size,之后每插入一条新的记录 ...
- 如何在java中使用sikuli进行自动化测试
很早之前写过一篇介绍sikuli的文章.本文简单介绍如何在java中使用sikuli进自动化测试. 图形脚本语言sikuli sikuli IDE可以完成常见的单击.右击.移动到.拖动等鼠标操作,ja ...
- Java中的守护线程 & 非守护线程(简介)
Java中的守护线程 & 非守护线程 守护线程 (Daemon Thread) 非守护线程,又称用户线程(User Thread) 用个比较通俗的比如,任何一个守护线程都是整个JVM中所有非守 ...
- c#中如何跨线程调用windows窗体控件
c#中如何跨线程调用windows窗体控件? 我们在做winform应用的时候,大部分情况下都会碰到使用多线程控制界面上控件信息的问题.然而我们并不能用传统方法来做这个问题,下面我将详细的介绍.首 ...
随机推荐
- My First
刚入职不到2个月吧,还在实习,月底拿毕业证转正.工作期间遇到很多麻烦问题,有的解决了,有的解决不了,换了个方法实现,挺无奈的.弄个博客,记录下平常遇到的问题和解决方式,也省的每次拿个笔记下来了…… 公 ...
- POJ3006-Dirichlet's Theorem on Arithmetic Progressions
题意: 设一个等差数列,首元素为a,公差为d 现在要求输入a,d,n ,要求找出属于该等差数列中的第n个素数并输出 思路:空间换时间是个主旋律.素数表的生成用素数筛选法.方法是从2开始,对每个目前还标 ...
- 注解@RequestParam——取请求参数
一.创建index.jsp 创建一个用来发送请求的测试jsp <a href="springMVC/testRequestParam?username=lzj&age=20&q ...
- java课堂实践(5月17日)20155317 王新玮
对P145 MathTool.java 代码托管 在IDEA中,使用JUnit进行单元测试,测试用例不少于三个,要包含正常情况,边界情况.提交测试代码和运行结果截图,加上学号水印,提交码云代码链接. ...
- 考研编程练习----m叉树先序和后序所包含的情况
题目描述: We are all familiar with pre-order, in-order and post-order traversals of binary trees. A comm ...
- C#:通过NuGet程序包下载CefSharp来加载谷歌浏览器
------------吾亦无他,唯手熟尔,谦卑若愚,好学若饥------------- 首先我讲明一下我要做的,公司有个C# wpf的项目需要我把一个开发好的网页嵌入到客户端当中,由于种种原因,我放 ...
- 关于Eclipse在servlet中连接数据库时出现驱动加载失败的解决
问题:在队友发来的项目中想将他获取到的数据通过数据库储存,出现驱动加载失败问题 解决:首先百度了下相关情况,大多数都是说下载mysql-connector-java-5.1.39-bin.jar包,然 ...
- JY播放器【网易云音乐破解下载】
今天给大家带来一款神器----JY播放器.可以直接下载网易云音乐的歌曲. 目前已经支持平台(蜻蜓FM.喜马拉雅FM.网易云音乐.QQ音乐) 使用方法: 在电脑打开网易云音乐或者网站找到你要听的歌曲或歌 ...
- MapReduce和yarn
1.Mapreduce是什么? Mapreduce是一个分布式运算程序的编程框架,是用户开发“基于hadoop的数据分析应用”的核心框架: Mapreduce核心功能是将用户编写的业务逻辑代码和自带默 ...
- 堆中的路径(MOOC)
将一系列给定数字插入一个初始为空的小顶堆H[].随后对任意给定的下标i,打印从H[i]到根结点的路径. 输入格式: 每组测试第1行包含2个正整数N和M(≤),分别是插入元素的个数.以及需要打印的路径条 ...