首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > JAVA > J2SE开发 >

java多线程共享Vector抛错误

2013-11-21 
java多线程共享Vector抛异常本帖最后由 iamascv 于 2013-11-14 17:05:38 编辑import java.io.BufferedRead

java多线程共享Vector抛异常
本帖最后由 iamascv 于 2013-11-14 17:05:38 编辑

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Vector;

public class MT {
/**
 * @param
 */
private static Vector v = new Vector();

public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
PutThread p = new PutThread(v);
Thread t = new Thread(p);
GetThread g = new GetThread(v);
GetThread g2 = new GetThread(v);
GetThread g3 = new GetThread(v);

t.start();
t.sleep(10);
g.start();
g2.start();
g3.start();
}

}

class PutThread implements Runnable {
private Vector vv;

public PutThread(Vector v) {
this.vv = v;
}

public void run() {
BufferedReader br = null;
try {
br = new BufferedReader(new InputStreamReader(new FileInputStream(
"d:\\a.txt")));
String tmp = "";
while ((tmp = br.readLine()) != null) {
System.out.println("before put-----" + vv.size());
vv.add(tmp);
System.out.println("after put-----" + vv.size());
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}

}
}

class GetThread extends Thread {

private Vector vv;

public GetThread(Vector v) {
this.vv = v;
}

@Override
public void run() {
while (!vv.isEmpty()) {
System.out.println(Thread.currentThread().getName()
+ "===before get=====" + vv.size());
try {
Object o = vv.remove(0);
                                this.sleep(10);
} catch (Exception e) {
System.out.println(Thread.currentThread().getName()
+ " ****************crashed****************");
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()
+ "===after get=====" + vv.size());
}

}
}


其中a.txt是一个约有5万行的文本

执行的时候,会抛

...
before put-----5
Thread-2===before get=====3
Thread-1===after get=====3
Thread-0===before get=====4
Thread-2===after get=====3
Thread-1===before get=====3
after put-----4
Thread-1===after get=====1
Thread-2===before get=====2
Thread-0===after get=====2
Thread-2===after get=====0
Thread-1===before get=====1
before put-----1
after put-----1
Thread-1 ****************crashed****************
before put-----1
after put-----2
before put-----2
after put-----3
before put-----3
after put-----4
before put-----4
after put-----5
java.lang.ArrayIndexOutOfBoundsException: Array index out of range: 0
before put-----5
after put-----6
before put-----6at java.util.Vector.remove(Vector.java:777)
at GetThread.run(GetThread.java:17)

after put-----7
Thread-1===after get=====7
before put-----7
Thread-1===before get=====7
after put-----8
Thread-1===after get=====7
before put-----7
Thread-1===before get=====7
after put-----8
Thread-1===after get=====7
before put-----7
Thread-1===before get=====7
after put-----8
Thread-1===after get=====7
before put-----7
Thread-1===before get=====7
after put-----8
Thread-1===after get=====7
before put-----7
Thread-1===before get=====7
after put-----8
Thread-1===after get=====7
before put-----7
Thread-1===before get=====7
after put-----8
...


Vector不是线程安全的吗,为什么会抛异常呢?
crashed之后,为什么后面的进程还有 Thread-1 呢? java 多线程 Vectoer Exception
[解决办法]
线程安全也是相对的
while (!vv.isEmpty())  判断和下面的remove动作不是原子操作,也就是没有共享锁。
你可以这样理解:
Thread1 while (!vv.isEmpty()) true 。进去后,正好Thread2 也进去了,并且先于Thread1 Remove了


这个时候就报错了。java.lang.ArrayIndexOutOfBoundsException: Array index out of range: 0
[解决办法]
Vector的线程安全,指的是:它的任意一个public的方法是现场安全的。你的这种“先空,再操作”的逻辑,里面涉及了Vector的2个方法:isEmpty()和remove()。这样会造成并发的状态不一致问题。你可以看看《java并发编程》这本书,里面对你遇到的这类问题进行了详细的阐述。
[解决办法]
Vector是线程安全的

但你的代码线程不安全啊。 状态不一致,冲突了。
[解决办法]
看了一下你的代码。你的这种设计,不就是“生产者-消费者”模式么?为什么不采用具有“阻塞”的并发队列呢?比如:BlockingQueue.
关于“生产者-消费者”,我这里有个例子,你可以看看:
http://kanpiaoxue.iteye.com/admin/blogs/1974681
[解决办法]
数据线程安全是指你存跟取的时候集合的数据是安全的。
比如两个个线程对v同时存入值,会有先后顺序,两个值都能存入的集合中。
如果非线程安全的情况下有可能第一个执行的线程存进去的值会被第二个线程存进去的值所覆盖。
你那些代码并不能做为线程安全的测试。
[解决办法]


[解决办法]
引用:
嗯,明白了
不过为什么Thread-1抛异常之后,后面还在执行呢?


你用的try catch 是捕获异常,不是抛出异常。
[解决办法]
Vector本身是线程安全的。
但是你的操作不安全。

你catch的异常只是做打印,所以继续走
System.out.println(Thread.currentThread().getName()
                        + " ****************crashed****************");
                e.printStackTrace();

如果你捕捉到此异常System.exit(0);那程序就退出了

热点排行