转载请注明出处
/pony_maggie/article/details/42587821
作者:小马
先看一个示例, 多个计数器线程实例(TwoCounter), 每个实例有两个整型计数器,线程运行时,两个计数器开始"同时"累加,还有若干个监控器线程实例(Watcher),每个实例都会利用自己的"线程时间"监控所有的计数器实例,当某个实例中的count1和count2不相等时,就会显示"unsynched"。
贴出一些关键的代码,
class TwoCounter extends Thread
{
private boolean started = false;
private JTextField t1 = new JTextField(5);
private JTextField t2 = new JTextField(5);
private JLabel label = new JLabel("count1 == count2");
private int count1 = 0, count2 = 0;
public TwoCounter()
{
JPanel p = new JPanel();
p.add(t1);
p.add(t2);
p.add(label);
getContentPane().add(p);
}
//为了防止同一个线程多次启动
public void start()
{
if(!started)
{
started = true;
super.start();
}
}
public void run()
{
while(true)
{
t1.setText(Integer.toString(count1++));
t2.setText(Integer.toString(count2++));
try
{
sleep(500);
}
catch (InterruptedException e)
{
System.err.println("Interrupted");
}
}
}
//用来监视计算器的对外API
public void synchTest()
{
Sharing1.incrementAccess();//追踪访问次数
if(count1 != count2)
{
label.setText("Unsynched");
}
}
}
class Watcher extends Thread
{
public Watcher()
{
start();
}
public void run()
{
while(true)
{
for(int i = 0; i < s.length; i++)
{
s[i].synchTest();
}
try
{
sleep(500);
}
catch (InterruptedException e)
{
System.err.println("interrupted");
}
}
}
}
这个demo的要演示的功能看起来有些匪夷所思,从代码上看,两个计数器应该是"永远"相等的,毕竟每个计数器实例是独立的,有自己的textField, label, 计数器并且同时累加,怎么会有不等的情况呢?
先看看运行的结果:
结果证明确实有不相等的情况出现,原因是什么呢?
再回头看一下TwoCounter中的run函数,线程的执行函数,下面两行:
t1.setText(Integer.toString(count1++));
t2.setText(Integer.toString(count2++));
一般情况下,这两行会"同时"(CPU中的同一个时间片)执行,这时count1和count2相等的情况。但是因为是多个线程,你永远不知道某个线程什么时候获取执行的机会,
有可能Watcher线程在t1和t2之间执行了,这个就是"不相等的情况"。 这个示例说明多线程在某些时候可能会给我们带来麻烦,有很多应用场景我们希望类似上面t1和t2要能同时执行,不然可能带来严重的后果。好在java有一种同步机制,可以解决这样的问题,下一篇接着讲。