如何通过工作线程更改变量

时间:2013-07-31 14:32:13

标签: java multithreading

有优雅的方式吗?或者总是可以避免,因为人们可以使用更好的设计模式?

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");
    }
}

5 个答案:

答案 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
    }

}