并发队列
数据结构
什么是数据结构:数据结构(data structure)是带有结构特性的数据元素的集合,它研究的是数据的逻辑结构和数据的物理结构以及它们之间的相互关系,并对这种结构定义相适应的运算,设计出相应的算法,并确保经过这些运算以后所得到的新结构仍保持原来的结构类型
简而言之,数据结构是相互之间存在一种或多种特定关系的数据元素的集合,即带“结构”的数据元素的集合。“结构”就是指数据元素之间存在的关系,分为逻辑结构和存储结构
ps:数据结构是计算机组织数据和存储数据的方式
数据结构的分类:
- 线性结构:线性结构是一个有序数据元素的集合,线性表就是典型的线性结构,还有栈、队列和串等都属于线性结构
- 非线性结构:简单地说,非线性结构就是表中各个结点之间具有多个对应关系,在实际应用中,数组、广义表、树结构和图结构等数据结构都属于非线性结构
常见的数据结构有很多,例如栈,对列,数组,线性表,图,堆等
队列都有那些特点
1)队列是先进先出的,这点类似于现实世界中的排队打饭
2)队列只能是从队尾进入,队首出去
3)往队列中添加数据称之为入队,取出队列中的数据称之为是出队
ConcurrentLinkedQueue
那么JDK中有哪些并发队列呢?
JDK中的并发队列都是基于Quene这个接口展开,并发队列在JDK提供了两套实现,一个是以ConcurrentLinkedQueue为代表的高性能队列,一个是以BlockingQueue接口为代表的阻塞队列,无论哪一种都会继承Queue接口
ConcurrentLinkedQueue::是一个适用于高并发场景下的队列,通过无锁的方式(那么它怎么保证线程安全呢,其实它是靠自旋(锁)+CAS算法实现的,这个怎么到底是怎样的呢,我们需要继续深入研究才能明白,后续可能会讲), 实现了高并发状态下的高性能,通常ConcurrentLinkedQueue性能好于BlockingQueue.它是一个基于链接节点的无界线程安全队列。该队列的元素遵循先进先出的原则。头是最先加入的,尾是最近加入的,该队列不允许null元素
翻译成大白话:
1)ConcurrentLinkedQueue能够保证多线程并发环境下的线程安全
2)ConcurrentLinkedQueue是无界限的(可以存入多个数据,不限定长度)
3)ConcurrentLinkedQueue是不阻塞的
4)ConcurrentLinkedQueue是FIFO的
ConcurrentLinkedQueue中对应的重要方法如下所示:
-
add( ) 和offer() 都是加入元素的方法(在ConcurrentLinkedQueue中这俩个方法没有任何区别)
-
poll() 和peek() 都是取头元素节点,区别在于前者会删除元素,后者不会。
例如:
package com.rj.bd.jucs;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.ConcurrentLinkedQueue;
public class Test {
public static void main(String[] args) {
//1.初始化ConcurrentLinkedQueue
ConcurrentLinkedQueue<String> concurrentLinkedQueue=new ConcurrentLinkedQueue<String>();
//2.入队
concurrentLinkedQueue.add("杨过");
concurrentLinkedQueue.offer("郭靖");
/*3.出队
System.out.println(concurrentLinkedQueue.peek());
System.out.println(concurrentLinkedQueue.poll());//此时我们会发现18行和19行的结果一样,那说明这两个方法都是取出数据,但是,如果18行也改成poll()那么20行的结果就是null
System.out.println(concurrentLinkedQueue.poll());*/
//4.获取长度
System.out.println(concurrentLinkedQueue.size());
//5.remove:从队列中移除指定元素的单个实例(如果存在)
System.out.println("remove:"+concurrentLinkedQueue.remove("郭靖"));
//6.contains:如果此队列包含指定元素,则返回 true
System.out.println("contains:"+concurrentLinkedQueue.contains("郭靖"));
//7.iterator:迭代遍历
concurrentLinkedQueue.add("黄蓉");
concurrentLinkedQueue.offer("柯镇恶");
Iterator<String> it = concurrentLinkedQueue.iterator();
while (it.hasNext())
{
String everyStr = (String) it.next();
System.out.println(everyStr);
}
//7.ConcurrentLinkedQueue的有参数构造器: 创建一个最初包含给定 collection 元素的 ConcurrentLinkedQueue,按照此 collection 迭代器的遍历顺序来添加元素。
List list=new ArrayList();
list.add("aaa");
list.add("ccc");
list.add("bbb");
ConcurrentLinkedQueue con2=new ConcurrentLinkedQueue(list);
System.out.println(con2);
}
}
size()和isEmpty()对比
package com.rj.bd;
/**
* @desc ConcurrentLinkedQueue中size()和isEmpty()方法的对比
* 得出结论:size()方法比isEmpty()耗时更长,原因是size() 是要遍历一遍集合的.
*
*
*
*
*/
import java.util.concurrent.ConcurrentLinkedQueue;
public class Test02 {
public static void main(String[] args) {
useSize();
useIsEmpty();
}
public static void useSize() {
final ConcurrentLinkedQueue<Long> queue = new ConcurrentLinkedQueue<>();
for(int i = 0; i < 100000; i++) {
queue.offer(i);
}
System.out.println("========= offer done ==========");
long startTime = System.currentTimeMillis();
while(queue.size() > 0) {
queue.poll();
}
System.out.println("========= poll done ==========");
System.out.println("useSize: " + (System.currentTimeMillis() - startTime));
}
public static void useIsEmpty() {
final ConcurrentLinkedQueue<Long> queue = new ConcurrentLinkedQueue<>();
for(int i = 0; i < 100000; i++) {
queue.offer(i);
}
System.out.println("========= offer done ==========");
long startTime = System.currentTimeMillis();
while(!queue.isEmpty()) {
queue.poll();
}
System.out.println("========= poll done ==========");
System.out.println("useIsEmpty: " + (System.currentTimeMillis() - startTime));
}
}
commons-io包下的工具类
FileUtils的使用
- FileUtils.readLines : 读取文件中的每一行
- FileUtils.writeStringToFile : 将字符串写入到文件中
- FileUtils.writeLines : 逐行写入文件
- FileUtils.copyFile : 文件复制
- FileUtils.copyURLToFile : 根据URL进行赋值,产生的结果就是相当于是另存为
- FileUtils.deleteDirectory : 删除文件或者是文件夹
- FileUtils.sizeOf : 获取某一路径下文件的大小
fileSystemUtils的使用
package com.rj.bd.common2;
import java.io.IOException;
import org.apache.commons.io.FileSystemUtils;
/**
* @desc FileSystemUtils类:文件系统的一个工具类
* @time 2018-10-25 下午02:46:30
*
*/
public class FileSystemTools {
/**
* @desc 获取该路路径下的可用空间
* @param pathname
* @throws IOException
*/
public void getSpace(String pathname) throws IOException
{
System.out.println(FileSystemUtils.freeSpaceKb(pathname)/1024/1024+"GB");
System.out.println(FileSystemUtils.freeSpaceKb(pathname)/1024+"MB");
}
}
package com.rj.bd.common2;
import java.io.IOException;
/**
* @desc 测试类:测试FileSystemUtils类
* @time 2018-10-25 下午03:08:05
*
*/
public class CeShi {
public static void main(String[] args) throws IOException {
FileSystemTools fTools=new FileSystemTools();
fTools.getSpace("D:/");
}
}
IOUtils的使用
package com.rj.bd.common3;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
/**
* @desc 测试类:测试IOUtils类:实现IO流操作(非本地的)
* @time 2018-10-25 下午03:08:05
*
*/
public class CeShi {
public static void main(String[] args) throws IOException {
InputStream in = new URL("https://d-ring.i4.cn/audio/2019/10/23/14/1571813891640_677830.mp3").openStream();
byte[] array = IOUtils.toByteArray(in);
FileUtils.writeByteArrayToFile(new File("E:/zp/123.mp3"), array);
}
}
FileNameUtils的使用
(1)显示linux路径:"+FilenameUtils.normalizeNoEndSeparator(fileFullName);
(2)合并目录和文件名为文件全路径:"+FilenameUtils.concat(fileDirectory, fileName);
(3)文件路径去除目录和后缀后的文件名:"+FilenameUtils.getBaseName(fileFullName);
(4)获取文件的后缀:"+FilenameUtils.getExtension(fileFullName);
(5)获取文件的完整目录:"+FilenameUtils.getFullPath(fileFullName);
(6)获取文件的目录不包含结束符:"+FilenameUtils.getFullPathNoEndSeparator(fileFullName); (7)获取文件名称,包含后缀:"+FilenameUtils.getName(fileFullName);
(8)去除前缀的路径:"+FilenameUtils.getPath(fileFullName);
(9)去除前缀并结尾去除分隔符:"+FilenameUtils.getPathNoEndSeparator(fileFullName);
(10)获取前缀:"+FilenameUtils.getPrefix(fileFullName);
(11)获取前缀长度:"+FilenameUtils.getPrefixLength(fileFullName);
(12)获取最后一个.的位置:"+FilenameUtils.indexOfExtension(fileFullName);
(13)获取最后一个/的位置:"+FilenameUtils.indexOfLastSeparator(fileFullName);
(14)获取当前系统格式化路径:"+FilenameUtils.normalize(fileFullName);
(16)获取当前系统无结尾分隔符的径:"+FilenameUtils.normalizeNoEndSeparator(fileDirectory);
(17)获取linux系统无结尾分隔符的径:"+FilenameUtils.normalizeNoEndSeparator(fileDirectory);(18)移除文件的扩展名:"+FilenameUtils.removeExtension(fileFullName));
(19)转换分隔符为当前系统分隔符:"+FilenameUtils.separatorsToSystem(fileFullName);
(20)转换分隔符为linux系统分隔符:"+FilenameUtils.separatorsToUnix(fileFullName);
(21)转换分隔符为windows系统分隔符:"+FilenameUtils.separatorsToWindows(fileFullName);
(22)判断目录下是否包含指定文件或目录:"+FilenameUtils.directoryContains(fileDirectory, fileName);
String linuxFileName = FilenameUtils.normalize(fileFullName);
(23)判断文件路径是否相同:"+FilenameUtils.equals(fileFullName, linuxFileName);
(24)判断文件路径是否相同,格式化并大小写不敏感:"+FilenameUtils.equals(fileFullName,FilenameUtils.normalize(fileFullName),true,IOCase.INSENSITIVE);
(25)判断文件路径是否相同,格式化并大小写敏感:" + FilenameUtils.equalsNormalized(fileFullName, linuxFileName);
(26)判断文件路径是否相同,不格式化,大小写敏感根据系统规则:windows:敏感;linux:不敏感:"+ FilenameUtils.equalsOnSystem(fileFullName, linuxFileName));
(27)判断文件扩展名是否包含在指定集合中:"+ FilenameUtils.isExtension(fileFullName, extensions);
(28)判断文件扩展名是否等于指定扩展名:"+ FilenameUtils.isExtension(fileFullName, “txt”);
(29)判断文件扩展名是否包含在指定字符串数组中:"+ FilenameUtils.isExtension(fileFullName, new String[]{“txt”,“java”});
(30)判断文件扩展名是否和指定规则匹配,大小写敏感:"+ FilenameUtils.wildcardMatch(fileName, “.???");
(31)判断文件扩展名是否和指定规则匹配,大小写不敏感:"+ FilenameUtils.wildcardMatch(fileName, ".???”,IOCase.INSENSITIVE);
(32)判断文件扩展名是否和指定规则匹配,根据系统判断敏感型:windows:不敏感;linux:敏感:"+FilenameUtils.wildcardMatchOnSystem(fileName, “*.???”);