- 題目一:
提供一個懶漢模式的單實例類實現。
要求:
1.考慮線程安全。
2.提供測試代碼,測試線程安全性。
public class Singleton {
public Singleton() {}
/**
* 內部靜態類實現單例
*/
private static class SingletonHolder{
private static final Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance(){
return SingletonHolder.INSTANCE;
}
public static void main(String[] args) {
for (int i = 0; i < 50; i++) {
new Thread(() -> System.out.println(Singleton.getInstance().hashCode())).start();
}
}
}
- 題目二
1.設計含最小函數min()、pop()、push()的棧AntMinStack,存儲數據元素爲int
2.AntMinStack中數據存儲使用Stack結構
要求:
1.AntMinStack實現測試,滿足棧特性
2.要求min、push、pop、的時間複雜度都是O(1)
public class AntMinStack {
Stack<Integer> stack;
Stack<Integer> min;
public AntMinStack(){
stack = new Stack<>();
min = new Stack<>();
}
public void push(int data){
stack.push(data);
if (min.isEmpty() || data <= min.peek()){
min.push(data);
}
}
public int pop() throws Exception{
if (stack.isEmpty()){
throw new Exception("EmptyStackException");
}
if (stack.peek() == min.peek()){
min.pop();
}
return stack.pop();
}
public int min() throws Exception{
if (min.isEmpty()){
throw new Exception("EmptyStackException");
}
return min.peek();
}
public static void main(String[] args) throws Exception{
AntMinStack antMinStack = new AntMinStack();
for (int i = 20; i >= 0; i--) {
antMinStack.push(i);
System.out.println("入棧:"+i+",最小值爲:"+antMinStack.min());
}
for (int i = 0; i < 19; i++) {
System.out.println("出棧:"+antMinStack.pop()+"最小值爲:"+antMinStack.min());
}
}
}
- 題目三
假設本地有一個文件夾,文件夾下面有若干文件(文件數大於50小於100),文件的存儲格式是文本格式(後綴名是.txt),文件的大小每個文件不會超過100k
文件格式如下:
2000102,100,98.32000103,101,73.32000104,102,98.32000105,100,101.32000106,101,45.3……
文件格式說明:文件每行都由三列構成,第一列是一個id,第二列是分組groupId, 第三列是指標quota。
id的數據類型是String, groupId的數據類型String, quota的數據類型float。
功能要求:1.把所有文件裏面的內容按照分組進行排序,輸出所有文件按照分組升序排序之後,每個分組下面的最小指標值。比如上面的數據輸出結果爲:100,2000102,98.3101,2000106,45.3102,2000104,98.3
非功能要求:
1.文件讀取要有線程池來執行,線程池的大小固定爲10,文件內容需要存儲到指定的內容數據結構當中
2.查找要求有獨立線程來執行,直接消費讀取線程池產生的內存數據結構。
3.文件讀取和排序要求併發作業,文件讀取只要產生了數據,就可以把數據交給排序線程進行消費,計算最小值。
代碼要求
1.重上面的要求語意裏面抽象出合適的設計模式。
2.需要考慮多線程的併發控制,同步機制。
3.代碼實現只能用JDK1.6或者1.8自帶的工具類
/**
*
* 生產者線程
* Author: Administrator Date: 2018年8月28日
*
*/
public class Producer implements Runnable{
private LinkedBlockingQueue<DataItem> queue;
private File file;
private CountDownLatch countDownLatch;
public Producer(LinkedBlockingQueue<DataItem> queue,File file,CountDownLatch countDownLatch) {
this.queue = queue;
this.file = file;
this.countDownLatch = countDownLatch;
}
@Override
public void run() {
try {
InputStreamReader read = new InputStreamReader(new FileInputStream(file));
BufferedReader br=new BufferedReader(read);
String line="";
String[] arrs=null;
while ((line=br.readLine())!=null) {
if (line.equals("")) {
continue;
}
arrs=line.split(",");
DataItem dataItem = new DataItem();
dataItem.setId(arrs[0]);
dataItem.setGroupId(arrs[1]);
dataItem.setQuota(new Float(arrs[2]));
queue.add(dataItem);
}
br.close();
read.close();
countDownLatch.countDown();
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
*
* 消費者線程
* Author: Administrator Date: 2018年8月28日
*
*/
public class Consumer implements Runnable{
private LinkedBlockingQueue<DataItem> queue;
private TreeMap<String, DataItem> treeMap;
private CountDownLatch countDownLatch;
public Consumer(LinkedBlockingQueue<DataItem> queue,TreeMap<String, DataItem> treeMap,CountDownLatch countDownLatch) {
this.queue = queue;
this.treeMap = treeMap;
this.countDownLatch = countDownLatch;
}
@Override
public void run() {
try {
while(true){
if (!queue.isEmpty()) {
DataItem dataItem = queue.take();
DataItem mydataItem = treeMap.get(dataItem.getGroupId());
if (mydataItem == null) {
treeMap.put(dataItem.getGroupId(), dataItem);
}else{
if (dataItem.getQuota() < mydataItem.getQuota()) {
treeMap.put(dataItem.getGroupId(), dataItem);
}
}
}else{
if(countDownLatch.getCount() <= 1){
countDownLatch.countDown();
break;
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
*
* 數據倉庫
* Author: Administrator Date: 2018年8月29日
*
*/
public class DataWareHouse {
private static final int THREAD_POOL_SIZE = 10;
private LinkedBlockingQueue<DataItem> queue;
private TreeMap<String, DataItem> treeMap;
private ExecutorService threadPool;
public DataWareHouse() {
queue = new LinkedBlockingQueue<>();
treeMap = new TreeMap<>(new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return Long.valueOf(o1).compareTo(Long.valueOf(o2));
}
});
threadPool = Executors.newFixedThreadPool(THREAD_POOL_SIZE);
}
public LinkedBlockingQueue<DataItem> getQueue() {
return queue;
}
public void setQueue(LinkedBlockingQueue<DataItem> queue) {
this.queue = queue;
}
public TreeMap<String, DataItem> getTreeMap() {
return treeMap;
}
public void setTreeMap(TreeMap<String, DataItem> treeMap) {
this.treeMap = treeMap;
}
public ExecutorService getThreadPool() {
return threadPool;
}
public void setThreadPool(ExecutorService threadPool) {
this.threadPool = threadPool;
}
}
/**
*
*
* Author: Administrator Date: 2018年8月28日
*
*/
public class DataItem {
/**
* id
*/
private String id;
/**
* 分組
*/
private String groupId;
/**
* 指標
*/
private Float quota;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getGroupId() {
return groupId;
}
public void setGroupId(String groupId) {
this.groupId = groupId;
}
public Float getQuota() {
return quota;
}
public void setQuota(Float quota) {
this.quota = quota;
}
}
public class Main {
public static void main(String[] args) {
String dirPath = "src/main/resources/files";
File dirFile = new File(dirPath);
File[] files = dirFile.listFiles();
DataWareHouse dataWareHouse = new DataWareHouse();
CountDownLatch countDownLatch = new CountDownLatch(files.length + 1);
for(File file : files){
Producer producer = new Producer(dataWareHouse.getQueue(), file,countDownLatch);
dataWareHouse.getThreadPool().execute(producer);
}
Consumer consumer = new Consumer(dataWareHouse.getQueue(), dataWareHouse.getTreeMap(),countDownLatch);
new Thread(consumer).start();
try {
countDownLatch.await();
dataWareHouse.getThreadPool().shutdownNow();
} catch (Exception e) {
e.printStackTrace();
}
Iterator<Entry<String, DataItem>> it = dataWareHouse.getTreeMap().entrySet().iterator();
while(it.hasNext()) {
Entry<String, DataItem> entry = it.next();
DataItem dataItem = entry.getValue();
System.out.println(dataItem.getGroupId() + "," + dataItem.getId()+","+dataItem.getQuota());
}
}
}
/**
* 創建測試數據
* @author jiangpan
* @title CreateDataTest.java
* @date 2018年8月29日
*
*/
public class CreateDataTest {
public static void main(String[] args) throws IOException {
String path = "src/main/resources/files/";
for (int i = 1; i < 100; i++) {
File file = new File(path+i+".txt");
if(!file.exists()){
file.createNewFile();
}
FileWriter fileWriter = new FileWriter(file);
BufferedWriter br = new BufferedWriter(fileWriter);
for (int j = 0; j < 5000; j++) {
br.write(getRandomData());
br.newLine();
}
br.close();
fileWriter.close();
}
System.out.println("success");
}
private static String getRandomData(){
Integer id = (int)(Math.random() * 1000000) + 1000000;
Integer groupId = (int)(Math.random() * 1000) + 100;
Float quota = (int)(Math.random() * 1000)/10.0f+60;
return id+","+groupId+","+quota;
}
}