疑似Google多线程面试题的Java实现
来到一个完全陌生的地方,即将一切从新开始,内心兴奋又忐忑。这几天忙着租房,装宽带直到今天才算告一段落,几经折腾,总算能安静的写写东西了。对我而言排解紧张情绪和压力的方式,就是投入一个问题的思考和解决中。之前在网上找相关的多线程问题,想通过演练来加深和熟练对多线程的掌握时,看到一个疑似Google的多线程面试题,感觉可以思考一下,题目如下:
启动4个线程,向4个文件A,B,C,D里写入数据,每个线程只能写一个值。
线程1:只写1
线程2:只写2
线程3:只写3
线程4:只写4
4个文件A,B,C,D。
程序运行起来,4个文件的写入结果如下:
A:12341234...
B:23412341...
C:34123412...
D:41234123...
这个题目主要是要解决线程调度的问题,可能原来是要求C/C++多线程的实现,不过语言不是问题的关键,我尝试用Java浩瀚的API堆了一个实现。先简单的说说思路,分析知有三个对象是必须的:线程对象,文件对象以及共享协调对象。线程对象不用多说了,扩展Thread,为其提供一个唯一的绑定值;文件对象可以使用虚拟文件先代替,反正写入文件和写入对象存储大同小异;最后就是负责调度线程写入文件的共享协调对象,这个对象的职责就是保证线程安全并且提供多线程正确写入数值到文件的方法。我能想到的方式有两种:一个是控制线程顺序依次写入文件,显然这种方式难度较大,毕竟线程之间的执行顺序很难保证;另一种就是线程竞争写入权,共享协调对象向获得写入权限的线程提供符合条件的文件写入。后者不用控制线程的执行顺序,并且各个线程完全相对独立,故而我采用了后面得方案进行实现:
Java代码
1. import java.io.File;
2. import java.io.FileWriter;
3. import java.io.IOException;
4. import java.io.PrintWriter;
5. import java.util.ArrayList;
6. import java.util.Collections;
7. import java.util.Comparator;
8. import java.util.List;
9. import java.util.concurrent.CountDownLatch;
10.
11. /**
12. * @author: yanxuxin
13. * @date: 2010-2-18
14. */
15. public class MultiThreadWriter {
16.
17. public static String[] FILE_NAMES = { "A", "B", "C", "D" };
18.
19. /** 文件路径 */
20. public static String FILE_PATH = "D:" + File.separator;
21.
22. private final List<MockOutput> outList = new ArrayList<MockOutput>(FILE_NAMES.length);
23.
24. /** 平衡优先级的比较器 */
25. private final Comparator<MockOutput> comparator = new PriorityComparator();
26.
27. /** 线程运行开关 */
28. private volatile boolean working = true;
29.
30. public static void main(String[] args) {
31. final MultiThreadWriter writer = new MultiThreadWriter();
32. final CountDownLatch start = new CountDownLatch(1); // 发令信号
33. final CountDownLatch end = new CountDownLatch(64); // 终止信号
34.
35. for (int i = 0; i < FILE_NAMES.length; i++) {
36. writer.new WriteWorker(writer, i + 1, start, end).start(); // 开启4个线程,每个线程分别只写入单一值
37. }
38.
39. start.countDown(); // 熟悉的开闸放狗
40.
41. try {
42. end.await(); // 等待其他子线程工作
43. }
44. catch (InterruptedException e) {
45. e.printStackTrace();
46. }
47.
48. writer.cleanAndDisplay(); // 计数为0时,打印最后一次调整了存储顺序的StringBuilder的值
49. }
50.
51. public MultiThreadWriter() {
52. try {
53. init();
54. }
55. catch (IOException e) {
56. e.printStackTrace();
57. }
58. }
59.
60. public boolean isWorking() {
61. return working;
62. }
63.
64. /**
65. * 供子线程调用并写入线程绑定的数值给文件和StringBuilder
66. *
67. * @param num
68. * @return
69. */
70. public boolean writeToOutput(int num) {
71. synchronized (outList) {
72. for (int i = 0; i < FILE_NAMES.length; i++) {
73. MockOutput output = outList.get(i);
74.
75. int lastest = output.getTheLatestNum();
76. if ((lastest % FILE_NAMES.length) + 1 == num) { // 取此output最后一次写入的值,判断是否满足再次写入
77. output.append(num);
78. output.setTheLatestNum(num);
79.
80. adjustPriority(); // 调整outList中各MockOutput实例的顺序
81.
82. &
补充:软件开发 , Java ,