CountDownLatch同步计数器 CountDownLatch是一个同步工具类,用来协调多个线程之间的同步,或者说起到线程之间的通信(而不是用作互斥的作用)。
CountDownLatch的用法
CountDownLatch典型用法:1、某一线程在开始运行前等待n个线程执行完毕。将CountDownLatch的计数器初始化为new CountDownLatch(n),每当一个任务线程执行完毕,就将计数器减1 countdownLatch.countDown(),当计数器的值变为0时,在CountDownLatch上await()的线程就会被唤醒。一个典型应用场景就是启动一个服务时,主线程需要等待多个组件加载完毕,之后再继续执行。
CountDownLatch典型用法:2、实现多个线程开始执行任务的最大并行性。注意是并行性,不是并发,强调的是多个线程在某一时刻同时开始执行。类似于赛跑,将多个线程放到起点,等待发令枪响,然后同时开跑。做法是初始化一个共享的CountDownLatch(1),将其计算器初始化为1,多个线程在开始执行任务前首先countdownlatch.await(),当主线程调用countDown()时,计数器变为0,多个线程同时被唤醒。
CountDownLatch的不足 CountDownLatch是一次性的,计算器的值只能在构造方法中初始化一次,之后没有任何机制再次对其设置值,当CountDownLatch使用完毕后,它不能再次被使用。
CountDownLatch类中有三个方法是最重要的:
//调用await()方法的线程会被挂起,它会等待直到count值为0才继续执行 public void await() throws InterruptedException { }; //和await()类似,只不过等待一定的时间后count值还没变为0的话就会继续执行 public boolean await(long timeout, TimeUnit unit) throws InterruptedException { }; //将count值减1 public void countDown() { };在工作中的使用:
public class ShellUtil{ public static ShellResult execute(String script){ ProcessBuilder builder = new ProcessBuilder("/bin/bash","-c", script.trim())); try{ Process process = buider.start(); CommandReader stdErrReader = new CommandReader(process.getErrorStream()); CommandReader stdOutReader = new CommandReader(process.getInputStream()); stdErrReader.start(); stdErrReader.waitReady(); stdOutReader.start(); stdOutReader.waitReady(); int exitVal = process.waitFor(); stdErrReader.waitFinished(); stdOutReader.waitFinished(); ShellResult shellResult = new ShellResult(); shellResult.errStr = stdErrReader.getOutputStr(); shellResult.normalLog = stdOutReader.getOutputStr(); shellResult.exitVal = exitVal; return shellResult; }catch(IOException | InterruptedException e){ ShellResult shellResult = new ShellResult(); shellResult.exitVal = -1; shellResult.errStr = e.gerMessage(); return shellResult; } } public static class ShellResult{ int exitVal; String errStr; String normalLog; public int getExitVal() { return exitVal; } public String getErrStr() { return errStr; } public String getNormalLog() { return normalLog; } } } class CommandReader extends Thread{ private InputStream is; private String outpurStr = ""; private CountDownLatch ready; private CountDownLatch finished; public CommandReader(InputStream is){ ready = new CountDownLatch(1); finished = new CountDownLatch(1); this.is = is; } public void run(){ StringBuilder stringBuilder = new StringBuilder(); String line = null; try(BufferedReader reader = new BufferedReader(new InputStreamReader(is))){ ready.countDown(); while((line=reader.readLine())!=null){ stringBuilder.append(line); stringBuilder.append("\n"); System.out.println(line); } outputStr = stringBuilder.toString(); }catch(IOException e){ e.printStackTrace(); }finally{ finished.countDown(); } } public void waitReady() throws InterruptedException { ready.await(); } public void waitFinished() throws InterruptedException { finished.await(); } public String getOutputStr() { return outputStr; } }原文连接:https://www.cnblogs.com/Lee_xy_z/p/10470181.html
解析json字符串详解 方法一:使用JSONObject来解析JSON数据 当根节点是”{}”使用JsonObject。当跟节点是”[]”使用jsonArray。 解析根节点为”[]”的json:
[ { "id": 1, "name": "七宝" }, { "id": 15, "name": "憨荻" } ] JSONArray jsonArray = new JSONArray(json); for(int i=0;i<jsonArray.length();i++){ JSONObject object = jsonArray.getJSONObject(i); String id = object.getString("id"); }解析根节点为”{}”的json:
{ "id": 1, "name": "七宝" } JSONObject object = new JSONObject(json); //等同于上面JSONObject jsonObject = (JSONObject)JSON.parse(json); String datasource = jsonObject.getString("name");方法二:使用JsonNode
//获取json字符串 {"sourceDbName":"${dbNameSource}", "sourceTable":"${tableSource}", "targetDbName":"${dbNameTarget}", "targetTable":"${tableTarget}", "screenCon":"${screenCon}", "isAll":"${isAll}", "branchNum":"${bbkNbr}", "fieldMapper":"${fieldsMapping}"} JsonNode root = objectMapper.readTree(stepConfig.getRequestTemplate()); Iterator<String> iter = root.fieldNames(); while(iter.hasNext()){ String key = iter.next(); String expr = root.get(Key).asText(); if (expr.startsWith("${") && expr.endsWith("}")) { String propertyName = expr.substring(2, expr.length() - 1); ((ObjectNode) root).put(key, BeanUtils.getProperty(task, propertyName)); } } //获取json数组 [{"resourceName":"${dbNameTarget}", "branchNum":"${bbkNbr}"},{"resourceName":"CDH", "branchNum":"100"}] JsonNode root = objectMapper.readTree(stepConfig.getResourceTemplate()); Iterator<JsonNode> nodeIter = root.elements(); while (nodeIter.hasNext()) { JsonNode child = nodeIter.next(); Iterator<String> iter = child.fieldNames(); replaceExpr(task, child, iter); TaskStepResource stepResource = objectMapper.readValue(child.traverse(), TaskStepResource.class); stepResource.setTaskId(task.getId()); stepResource.setStepCode(stepConfig.getStepCode()); taskStepResourceMapper.insert(stepResource); }方法三:GSON方式解析json字符串 首先需要添加GSON的jar包;gson.jar工具包使用起来非常简单,使用其可以非常便捷的在json字符串与javabean之间转换.
将javabean转换成字符串
Student stu = new Student(); stu.setName("张三"); stu.setAge(18); stu.setSex(true); Gson gson = new Gson(); //toJson方法参数即一个javabean。返回值即一个json字符串 String json = gson.toJson(stu); //打印为 {"name":"张三","age":18,"sex":true} System.out.println(json);将json转换为javabean :
String json = "{'name':'张三','age':18,'sex':true}"; Gson gson = new Gson(); // 将json 转化成 java 对象 //fromJson方法。参数一是json字符串。参数二是要转换的javabean //该javabean的字段名必须与json的key名字完全对应才能被正确解析。 Student stu = gson.fromJson(json, Student.class);Json 串解析 成 List
[{'name':'二阳','age':18,'sex':true},{'name':'小2阳','age':19,'sex':false},{'name':'小3马','age':20,'sex':true},{'name':'小4梦','age':21,'sex':false},{'name':'小5莲','age':22,'sex':true}] Gson gson = new Gson(); // 将 json 转化 成 List泛型 List<Student> stus = gson.fromJson(json, new TypeToken<List<Student>>() {}.getType());最近再看宁思潇潇的《摄影笔记》,其中通俗易懂的讲解了许多关于摄影的基础知识,比如焦距和取景、影调到底是什么、控制曝光补偿的三要素等等,整本书主要是从取景、曝光、虚实和构图四个方面去展开了描述。 透视与焦距的关系: 广角镜头会让画面有很强的纵深感,长焦镜头则会让画面更加扁平。远大近小就是透视的最简单说明,即离的越近,越觉得大,透视感越强烈;离得越远,越觉得小。 影调 影调就是指一张照片的明暗程度,明亮的照片就是高调,阴暗的照片就是低调,不亮不暗的就是中间调。控制一张照片的影调就是调节曝光补偿
1、影调的量化:曝光补偿,中间调=18%灰=0EV,每一个EV的亮度差就是2倍的关系 2、测光系统:
智能测光(多重、评价、矩证测光等)适合新手中央重点平均测光 重点考虑中心主题的曝光,然后加权其他背景的曝光点测光:对画面中的一点(1%到3%)进行测光 3、控制影调:调节曝光补偿 控制曝光补偿的三要素 一张照片的明暗是由感光器接受了多少光,并且有多大能力将光转化为呈现在照片上的明暗来决定的。照片的影调=曝光量 x 呈现能力 曝光量=感光器接受光的速度 x 曝光时间 感光器接受光的速度=环境光的强度 x 光圈 曝光量是感光器在曝光时间(快门)内接收到光的多少;
因得出: 传感器接收光的总量=光线强度 x 光圈 x 快门
用相机控制的影调=光圈 x 快门 x 感光度 1、光圈 孔径越大,光圈值越小,光圈越大,相对来说曝光量越大;光圈值与曝光量成反比,光圈与曝光量成正比。 一般来说光圈比f/2.8大的就算大光圈(f/1 、f/1.4 f/2 f/2.8) 光圈比f/8小的就算小光圈(f/8 f/11 f/16) 2、快门 曝光时间的简称,快门越快,曝光时间越短,相对来说曝光量越小;快门越慢,曝光时间越长,相对来说曝光量越大。 一般来说,比1/250秒快的就是高速快门;比1/60秒慢的就是低速快门 3、感光度 感官器对光线的敏感程度,感光度越高,照片的噪点就越多,看起来就会越粗糙,尽量选择较低的感光度 光线 光的三个特性:强度、方向、色温