今天堂妹子给同学们带来一个实例,一位Java程序员的实际工作情况。
实例涉及线程、ReadWriteLoc、synchronized等多个知识点,同时面对需求的沟通与解决,值得同学们收藏。
项目经理今天又接了一个客户需求,又要折磨我们这些程序员丝了。这个需求说起来很简单,做起来非常容易出错。
先简单描述一下:
这是一个在线文件编辑器。同一份文件,一个人在读的时候,其他人不能写;同理,一个人在写的时候,其他人也不能读。也就是说,要么读,要么写,这两件事情不能同时进行。
项目经理跟客户讲,“这个很容易实现的,我们是可以做的。”。什么都可以做,做不出来说是我们程序员能力不行,他一点责任都没有。领导发话了,不管怎么样,事情还是要做的。
看了一下需求,有两个问题,我得先问清楚,否则到时候做得不对,他又把负责推给我,我们项目经理经常搞这些让我背黑锅的事情。
“多人同时读可以吗?”
“当然可以啦!多少人来读都没关系,文件的内容不要变就行。”。
“多人同时写可以吗?”
“当然不行啦!你写别人也会写,文件不知道以哪份数据为准了。”。
他态度极其恶劣,算了,不跟他计较了,我的项目奖金还在他手里。赶紧完工,下班了还要回家抱小孩。
根据多年的项目实战经验,我写了一个超牛逼的 Data 类,来封装文件的数据。看起来是这样的:
稍微解释一下:
Data 类中封装了一个 char 数组类型的 buffer 成员变量。
在构造器中传入一个 size,表示 buffer 的长度,并在其中创建并初始化这个 buffer,使其每个字符都为“*”。
提供两个方法,一个负责读取,另一个负责写入。在读取方法中只需遍历 buffer,将结果不断 append 到一个 StringBuilder 中,最终将其转为 String 并返回。
在写入方法中传入一个字符,仍然是遍历 buffer,赋值 buffer 中的每个字符,这样可以使 buffer 中每个字符都是相同的。
故意在读写方法中加入了一个 sleep() 方法,让程序运行慢一点,模拟比较耗时的操作。而且故意让写入比读取慢一点,因为将 sleep() 方法放入了 write() 方法的循环体中,而 read() 方法却没有。
当然了,以上这个示例跑通了,我想项目经理那个需求也不难实现。这也是我们平时做开发的一种习惯,先快速地写个 Demo 出来,让领导们看看,技术上走通了,我们再实现具体的需求。
好了,不就是要同时读写吗?这不就是一个典型的多线程使用场景吗?于是我快速地写了一个读取线程,让它拼命地去读取 Data 中的数据。
在 ReaderThread 中通过一个死循环去不断地读取 Data 中的数据,并将结果打印出来。
再来一个写入线程,让它使劲地向 Data 中写入数据。
一次性可以传入一个字符串到 WriterThread 中,它将不断获取下一个字符(请见 next() 方法),并将该字符写入 Data 中。
如果让 ReaderThread 与 WriterThread 同时工作会怎样?不妨写了一个简单的 Client 类运行试试看。
我开启了 5 个 ReaderThread 与 2 个 WriterThread,模拟读得多写得少的情况,并将不同的数据写入 Data 中。
运行一下!
…
Thread-1 =
Tag标签: