您当前的位置:网站首页>一号红人,多线程 - Java 中怎么模仿真实的一起并发恳求?,牛肚的做法大全

一号红人,多线程 - Java 中怎么模仿真实的一起并发恳求?,牛肚的做法大全

2019-04-20 01:18:31 投稿作者:admin 围观人数:228 评论人数:0次

有时需求测验一下某个功用的并发功用,又不要想借助于其他东西,干脆就自己的开发言语,来一个并发央求就最便利了。

java中仿照并发央求,自然是很便利的,只需多开几个线程,建议央求就好了。可是,这种央求,一般会存在发动的先后顺序了,算不得实在的一同并发!怎样样才干做到实在的一同并发呢?是本文想说的点,java中供给了闭锁 CountDownLatch, 刚好就用来做这种事就最合适了。

只需求:

  1. 敞开n个线程,加一个闭锁,敞开一切线程;
  2. 待一切线程都预备好后,按下敞开按钮,就能够实在的建议并发央求了。
package com.test;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStr裤子尺码eam;
import java.io.I一号红人,多线程 - Java 中怎样仿照实在的一同并发央求?,牛肚的做法大全nputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
impor天边八卦t java.net.URL;
im醪糟的做法port java.util.concurrent.CountDownLatch;
public class LatchTest {
public static void main(String[] args) throws InterruptedException {
Runnable taskTemp = new Runnable() {
       // 留意,此处对错线程安全的,留坑
private int iCounter;
@Override
public void run() {
for(int i = 0; i < 10; i++) {
// 建议央求
// HttpClientOp.doGet("https://www.baidu.com/");
iCounter++;
System.out.println(S朗行ystem.na悲风神教noTime() + " [" + Thread.currentThread().getName() + "] iCounter = " + iCounter);
try {
Thread.sleep(100);
} catch (InterruptedEx一号红人,多线程 - Java 中怎样仿照实在的一同并发央求?,牛肚的做法大全ception e) {
e.printStackTrace()垃圾车视频;
}
}
}
};
Lat一号红人,多线程 - Java 中怎样仿照实在的一同并发央求?,牛肚的做法大全chTest latchTest = new LatchTest();
latchTest.startTaskAllInOnce(5, taskTemp);
}
public long startTaskAllInOnce(int threadNums, final Runnable task) throws InterruptedException {
final CountDownLatch startGate = new CountDownLatch(1);
final CountDownLatch endGate = new CountDownLatch(threadNums);
for(int i = 0; i < threadNums; i++) {
Thread t 乡村王妈妈= new Thread() {
public void run() {
try {
// 使线程在此等候,当开端门翻开时,一同涌入门中
startGate.await();
try {
task.run();
} finally {
// 将完毕门减1,减到0时,就能够敞开完毕门了
endGate.countDown();
}
} catch (InterruptedException ie) {
ie.一号红人,多线程 - Java 中怎样仿照实在的一同并发央求?,牛肚的做法大全printStackTrace();
}
}
};
t.start();
}
long startTime = System.nanoTime();
System.out.println(startTime + " [" + Thread.curren一号红人,多线程 - Java 中怎样仿照实在的一同并发央求?,牛肚的做法大全tThread() + "] All thread is ready, concurrent going...");
// 因敞开门只需一个开关,所以立马就敞开开端门
startGate.countDown();
// 等等完毕门敞开
endGate.await();
long endTime = System.nanoTime();
System.out.println(endTime + " [" + Thread.currentThread() + "] All thread is completed.");
return endTime - startTime;
}
}

其履行作用如下图所示:

httpClientOp 东西类,能够运用 老练的东西包,也能够自己写一个扼要的拜访办法,参阅如下:

class HttpClientOp {
public static String各色夫郎齐上堂 doGet(String httpurl) {
HttpURLConnection connection = null;
InputStream is = null;
BufferedReader br = null;
String result = null;// 回来成果字符串
try {
刘廷析// 创立长途url衔接目标
URL url = new URL(httpurl);
// 经过长途url衔接目标翻开一个衔接,强转成httpURLConnection类
connection = (HttpURLConnection) url.openConnection();
// 设置衔接方法:get
connection.setRequestMethod("GET");
// 设置衔接主机效劳器的超时时刻:15000毫秒
connection.setConnectTimeout(15000);
// 设置读取长途回来的数据时刻:60000毫秒
connection.setReadTimeout(60000);
// 发送央求
connection.connect();
// 经过connection衔接,获取输入流
if (connection.getResponseCode() == 200) {
is = connection.getInputStream();
// 封装输入流is,并指定字符集
br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
// 寄存数据
StringBuff不安沉着er sbf = new StringBuffer();
String temp = null;
while ((temp = br.readLine()) != null) {
sbf.append(temp);
sbf.append("\r\n");
}
result = sbf.toString();
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
// 封闭资源
if (null != br) {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (null != is) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
connection.disconnect();// 封闭长途衔接
}
return result;
}
public static String doPost(String httpUrl, String param) {
HttpURLConnection connection = null;
InputStream is = null;
OutputStream os = null;
BufferedReader br = null;
String result = null;
try {
URL url = new URL(httpUrl);
// 经过长途url衔接目标翻开衔接
connection = (HttpURLConnection) url.openConnection();
// 设置衔接央求方法
connection.setRequestMethod("POST");
// 设置衔接主机效劳器超时时刻:15000毫秒
connection.setConnectTimeout(15000);
// 设置读取主机效劳器回来数据超时时刻:60000期望宅邸毫秒
connection.setReadTimeout(60000);
// 默认值为:false,当向长途效劳器传送数据/写数据时,需求设置为true
connection.setDoOutput(true);
// 默认值为:true,当时向长途效劳读取数据时,设置为true,该参数可有可无
connection.setDoInput(true);
// 设置传入参数的格局:央求参数应该是 name1=value1&name2=value2 的方法。
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded")万有引力;
// 设置鉴权信息:Authorization: Bearer da3efcbf-0845-4fe3-8aba-ee040be542c0
connection.setRequestProperty("Authorization", "Bearer da3efcbf-0845-4fe3-8aba-ee040be542c0");
// 经过衔接目标获取一个输出流
os = connection.getOutputStream();
// 经过输出流目标将参数写出去/传输出去,它是经过字节数组写出的
os.write(param.getBytes());
// 经过衔接目标获取一个输入流,向长途读取
if (connection.getResponseCode() == 200) {
is = connection.getInputStream();
// 对输入流目标进行包装:charset依据作业项目组的要求来设置
br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
Stri一号红人,多线程 - Java 中怎样仿照实在的一同并发央求?,牛肚的做法大全ngBuffer sbf = new StringBuffer();
String temp = null;
// 循环遍历一行一行读取数据
while ((temp = br.readLine()) != null) {
sbf.a在线测速ppend(temp);
sbf.append("\r\n");
}
result = sbf.toString();
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
// 封闭资源
if (null !=强力透骨膜 br) {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (null != os) {
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (null != is) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
// 断开与长途地址url的衔接
connection.disconnect();
}
return result;
}
}

如上,就能够建议实在的并发央求了。

并发央求操作流程示意图如下:

此处设置了一道门,以确保一切线程能够一同收效。可是,此处的一同发动,也仅仅言语层面的东西,也并非肯定的一同并发。详细的调用还要依赖于CPU个数,线程数及操作系统的线程调度功用等,不过我们也无需纠结于这些了,要点在于了解原理!

与 CountDownLatch 有相似功用的,还有个东西栅门 CyclicBarrier, 也是供给一个等候一切线程抵达某一点后,再一同开端某个动作,作用共同,不过栅门的意图的确比较朴实,便是等候一切线程抵达,而前面说的闭锁 CountDownLatch 尽管完成的也是一切线程水沐晨光抵达后再开端,可是他的触发点其实是 最终那一个开关,所以侧要点是不一样的。

简略看一下栅门是怎样完成实在一同并发呢?示例如下:

// 与 闭锁 结构共同
public class LatchTest {
public static void main(String[] args) throws InterruptedException {
Runnable taskTemp = new Runnable() {
private int iCounter;
@Override
public void run() {
// 建议央求
// HttpClientOp.doGet("https://www.baidu.com/");
iCounter++;
System.out.println(System.nanoTime() + " [" + Thread.currentThre黄元甲ad().getName() + "] iCounter = " + iCounter);
}
};
LatchTest latchTest = new LatchTest();
// latchTest.startTaskAllInOnce(5, taskTem二氧化硫p);
latchTest.startNThreadsByBarrier(5, taskTemp);
}
public void startNThreadsByBarrier(int threadNums, Runnable finishTask) throws Interrupte陈婷dException {
// 设置栅门免除时的动作,比方初始化某些值
CyclicBarrier barrier = new CyclicBarrier(threadNums, finishTask);
// 发动 n 个线程,与栅门阀值共同,即当线程预备数抵达要求时,栅门刚好敞开,然后抵达一致操控作用
for (int i = 0; i < threadNums; i++) {
Thread.sleep(100);
new Thread(new CounterTask(barrier)).start();
}
System.out.println(Thread.currentThread().getName() + " out over...");
}
}
class CounterTask implements Runnable {
// 传入栅门,一般考虑更高雅方法
private CyclicBarrier barrier;
public CounterTask(final CyclicBarrier barrier) {
this.barrier = barrier;
}
public void run() {
System.out.println(Thread.currentThread().getName() + " - " + System.currentTimeMillis() + " is ready...");
try {
// 设置栅门,使在此等候,抵达方位的线程抵达要求即可敞开大门
barrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printSta鬼步舞教程ckTrace();
}
System.out.println(Thread.currentThread().getName() + " - " + Sys一号红人,多线程 - Java 中怎样仿照实在的一同并发央求?,牛肚的做法大全tem.currentTimeMillis() + " started...");
}
}

其运转成果如下图:

各有其使用场景吧,关键在于需求。就本文示例的需求来说,个人更乐意用闭锁一点,由于更可控了。可是代码却是多了,所以看你喜爱吧!

the end
我国大功率电动汽车充电标准制定工作,国内汽车平台一览