有优雅的方式吗?或者总是可以避免,因为人们可以使用更好的设计模式?
import java.util.ArrayList;
import java.util.List;
public class ForTest {
List<String> ls = new ArrayList<String>();
public static void main(String[] args) {
ForTest forTest=new ForTest();
System.out.println(forTest.ls.size());
new Thread(new Worker(forTest.ls)).start();
//size() does not change at all
System.out.println(forTest.ls.size());
}
}
class Worker implements Runnable{
List<String> list;
public Worker(List<String> li) {
this.list = li;
}
public void run(){
this.list.add("newItem");
}
}
答案 0 :(得分:2)
您的代码存在一些问题(特别是如果没有正确的同步,您使用的ArrayList不是线程安全的。)
但最明显的一点是,在你的run
方法有机会被执行之前,第二个println语句几乎总是被称为。
答案 1 :(得分:2)
您需要暂时制作主主题sleep()
。在新size()
有机会更新之前,Thread
会被调用。
new Thread(new Worker(forTest.ls)).start();
Thread.sleep(2000);
System.out.println(forTest.ls.size());
更好的方法是join()
到工作线程。当 worker 完成时,这将使 main 线程自动唤醒。
Thread worker = new Thread(new Worker(forTest.ls));
worker.start();
worker.join();
System.out.println(forTest.ls.size());
除此之外,如果 List 由多个线程共享和修改,则使用 synchronized ArrayList
来防止竞争条件。
List<String> ls = Collections.synchronizedList(new ArrayList<String>());
答案 2 :(得分:1)
你似乎错过了线程的想法。您的代码将无法正常工作,因为您的工作人员可能在您打印时未更新ls。如果您正在使用线程,则线程需要通信状态。这一切都非常复杂,我建议你阅读有关线程http://docs.oracle.com/javase/tutorial/essential/concurrency/
的java教程答案 3 :(得分:1)
请注意ArrayList
未同步,但Vector
是。您不能指望工作程序在启动其线程后运行一会儿。这就是列表大小尚未改变的原因。我想这不是你的完整例子,所以很难帮助你。 (如果这是你的完整例子,我想知道为什么你打算实施多线程解决方案。)
要知道工人何时完成,你可以join the threads。
答案 4 :(得分:1)
等待新线程实际开始运行你的代码+ make forTest
final以便能够访问它(也使用线程安全集合 - 最好的非同步a.k.a.非阻塞),例如
import java.util.Collection;
import java.util.concurrent.ConcurrentLinkedQueue;
public class ForTest {
Collection<String> ls = new ConcurrentLinkedQueue<String>();
public static void main(String[] args) throws InterruptedException {
final ForTest forTest = new ForTest();
System.out.println(forTest.ls.size());
int threads = 10;
for ( int i=0; i<threads; i++ ) {
new Thread(new Runnable() {
@Override
public void run() {
forTest.ls.add("newItem");
}
}).start();
}
Thread.sleep(1000);// wait for it !
System.out.println(forTest.ls.size()); // 10 unless your threads are really slow
}
}