JAVA的异步线程与同步线程问题.
public static void main(String[] args) {
int threadCount = 1000; // 线程数量(1000)
CountDownLatch countDownLatch = new CountDownLatch(threadCount);
List<Object> list = new ArrayList<Object>();
MyThreadTest myThreadTest = new MyThreadTest(list);
MySync mySync = MySync.getMySync(myThreadTest,countDownLatch);
// mySync = new MySync(myThreadTest,countDownLatch); // 为什么放开这段代码,会连 System.out.println("========:"+list.size()); 都不会执行了?
try {
for(int i =0;i<threadCount;i++){
mySync.run();
}
countDownLatch.await(); // 主线程等待所有子线程执行完成,再向下执行
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("========:"+list.size());
}
}
class MyThreadTest implements Runnable{
private List<Object> list;
private int i = 0;
public MyThreadTest(List<Object> list){
this.list = list;
}
@Override
public void run() {
i++;
list.add(new Object());
System.out.println(i);
}
}
class MySync{
private static CountDownLatch countDownLatch;
private static Runnable runn;
public MySync(){}
@SuppressWarnings("static-access")
public MySync(Runnable runn,CountDownLatch countDownLatch){
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(MySync.class);
enhancer.setCallback(new MethodInterceptorImpl());
MySync mySync = (MySync)enhancer.create();
mySync.countDownLatch = countDownLatch;
mySync.runn = runn;
}
@SuppressWarnings("static-access")
public static MySync getMySync(Runnable runn,CountDownLatch countDownLatch){
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(MySync.class);
enhancer.setCallback(new MethodInterceptorImpl());
MySync mySync = (MySync)enhancer.create();
mySync.countDownLatch = countDownLatch;
mySync.runn = runn;
return mySync;
}
public void run() throws InterruptedException {
MyThreadPool.execute(runn);
}
private static class MethodInterceptorImpl implements MethodInterceptor{
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
Object result = proxy.invokeSuper(obj, args);
if("public void MySync.run() throws java.lang.InterruptedException".equals(method.toString())){
countDownLatch.countDown(); // 完成一个子线程,减少一个计数
return result;
}
return result;
}
}
}
class MyThreadPool {
private static ExecutorService pool = null;
@SuppressWarnings("unchecked")
public static <T> T submit(Runnable runn){
T result = null;
if (pool == null) {
pool = Executors.newCachedThreadPool();
}
try {
Future<?> future = pool.submit(runn);
if(future.isDone()==true){
result = (T) future.get();
}
return result;
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
public static void execute(Runnable runn){
if (pool == null) {
pool = Executors.newCachedThreadPool();
}
try {
pool.execute(runn);
} catch (Exception e) {
e.printStackTrace();
}
}
}
System.out.println("========:"+list.size()); 使用计数来进行了同步,这段代码不应该是最后才会输出的吗?测试结果是不确定什么时候输出.
如果放开注释的那段代码,为什么连System.out.println("========:"+list.size()); 都不输出了?这是什么原因造成的?(不知道这段代码还有什么BUG,请各位大神指导)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
![扫码二维码加入Web技术交流群](/public/img/jiaqun_03.jpg)
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
先回答楼主的问题
CGLIB
字节码增强是对的你MySync
的方法进行增强,你文中的步骤是先执行MySync.run()
,然后再把线程丢入线程池,所以在执行MySync.run()
的时候就已经执行countDownLatch.countDown()
了,所以这里会出现一个情况是,countDownLatch.await()
的时候线程池里面还有茫茫多的线程在运行,所以list
的size
是随机的你直接放开
mySync = new MySync(myThreadTest,countDownLatch)
这段代码以后,构造器直接构造MySync
是没有经过CGLIB
加强的类,MySync mySync = (MySync) enhancer.create();mySync.countDownLatch = countDownLatch;mySync.runn = runn;
你在构造器里面增强的这个MySync,随着构造方法的结束,就被垃圾回收器回收了再来说说楼主程序的问题
if("public void MySync.run() throws java.lang.InterruptedException".equals(method.toString())
这一段代码,可以用method.getName()
来比较MyThreadTest
这个线程类,在run()
中执行i++
不是线程安全的,并且因为list也不是先后才能安全的,所以list.add()也会出现线程竞争问题首先,我想吐槽一下,代码确实很乱,看了老半天。
总结一下,你这里主要使用的是 CountDownLatch 和 CGLIB 字节码增强技术。
CountDownLatch 的主要功能是它允许一个或多个线程一直等待,直到其他线程的操作执行完后再执行。但是因为每个线程在执行完要在 finally 块调用 countdown() 方法,所以想利用 CGLIB 在线程执行完之后,自动调用 coundown()方法。但问题也就出现在这里: