几个程序解惑java多线程
来源:互联网 发布:visio网络拓扑图素材 编辑:程序博客网 时间:2024/06/06 06:47
public class Test implements Runnable{Thrd thd;Test2(Thrd thd){this.thd = thd;}public void run(){while(true){int v = thd.getNext();System.out.println(Thread.currentThread().getName()+" : "+v);try{Thread.sleep(1000);}catch(Exception e){}}}public static void main(String args[]){new Thread(new Test(new Thrd())).start();new Thread(new Test(new Thrd())).start();}}class Thrd{private int value = 0;public synchronized int getNext(){return value++;}}
这里在类Thrd中getNext方法使用了synchronized,也就是说这是一个同步方法,那么Test的main方法中,返回的value是不是会不同呢。运行程序(这里用了死循环)发现两个线程之间并没有同步,为什么呢?
原因很简单对于每个线程,我们传递了不同的Thrd类的实例,每个实例都有自己的getNext方法,二者之间是不同的。
现在我们把Thrd类做如下修改:
class Thrd{private static int value = 0;public synchronized static int getNext(){return value++;}}
运行程序,发现现在value在两个线程之间实现了同步。而原因就是现在getNext方法成为了类方法,两个线程访问的是同一个方法实例,所以可以同步。
现在给出一个复杂一点的程序(论坛上找的),我们可以按照上面的思路分析了。
import java.util.*;public class Test extends Thread{ private String st; private static List<String> list = new ArrayList<String>(); public Test(int i) { st = "str" + i; } public static void main(String[] args) throws Exception { String[] arr = new String[10]; for (int i = 0; i < arr.length; i++) { arr[i] = "str" + i; list.add(arr[i]); } for (int i = 0; i < arr.length; i++) { Test test = new Test(i); test.start(); } while(true){ if (list.isEmpty()) { break; } sleep(500); } System.out.println("finished"); } public void run() { removeStr(st); System.out.println(st); } public synchronized static void removeStr(String str) { Iterator<String> it = list.iterator(); while (it.hasNext()) { String strTemp = it.next(); if (strTemp.equals(str)) { it.remove(); break; } } } public synchronized static boolean isEmpty() { return list.isEmpty(); }}现在程序变得复杂了,而且由于包含了对线程非安全的list的操作,难度增大了。
这个程序是正确的,假如现在把方法removeStr和isEmpty前面的static去掉(如前所述,这时方法变为每个程私有的),程序可能会出现3中运行结果。下面我们一一分析。
首先需要说明的是,Test test = new Test(i); test.start();从这两句可知,第i个线程st=“stri”;线程start之后,每个线程从list中寻找元素跟stri相同的元素,并将其删除。其中,list是static的,每个线程共享。
1.运行正常结束。
这取决于一种特定的线程执行顺序,就是每个线程在对list进行操作的时候没有形成竞争条件,最后恰好删除list中所有元素,main函数中list.isEmpty()为真,循环结束,main也随之结束。
2.死循环。
这个是因为--size(通过remove源码可以知道)时,被另外一个线程抢占并同样进行了--size的操作。(考虑每一个线程的工作栈,事先会对size进行拷贝,size被另外一个线程改变后,上一个线程看到的还是旧的size值)
3.抛出ConcurrentModificationException。
原因是其中一个线程在it.next()与it.remove()之间被另外一个线程抢占并执行进行了删除操作。
而且还可以看到,每个线程的工作栈中并没有对list集合中的元素进行拷贝,只是拷贝了引用。否则的话,会有更多的问题。
- 几个程序解惑java多线程
- java解惑--多线程
- JAVA解惑---String创建了几个对象
- JAVA解惑---String创建了几个对象
- java面试题解惑 之 多线程
- Java多线程编程那些事:volatile解惑
- java解惑--谜题16:行打印程序
- 几个java小程序
- JAVA 多线程的几个误区
- Java多线程几个例子学习
- java多线程--几个多线程面试题小结
- 《Java解惑》
- java解惑
- java解惑
- java解惑
- java---解惑--
- JAVA解惑
- java解惑
- c++中while和for的优缺点
- 14382Life is beautiful
- 不带头节点的头尾插法
- chrome运行webdriver脚本提示--ignore-certificate-errors
- 关于WIN7+VS2013+WDK8.1做出一个.sys文件
- 几个程序解惑java多线程
- 数组指针和指针数组
- 山外论坛每日一贴的学习
- 设计模式入门-观察者模式
- 编写程序重载+
- JVM(三)内存模型
- 美图公司安排了较长的时间,让参会记者提问
- IOS显示gif图片,超简单方法
- 第十三章:13.2 工作管理