Heim  >  Fragen und Antworten  >  Hauptteil

java - 异步情况下的循环,怎么解决这个问题

PHPzPHPz2719 Tage vor453

Antworte allen(6)Ich werde antworten

  • 伊谢尔伦

    伊谢尔伦2017-04-18 10:10:52

    synchronized关键字

    Antwort
    0
  • ringa_lee

    ringa_lee2017-04-18 10:10:52

    给list加上volatile关键字

    Antwort
    0
  • 阿神

    阿神2017-04-18 10:10:52

    今天刚刚看过并发编程实战关于可变对象的安全发布与访问:
    安全发布:

    1. 在静态初始化函数中初始化一个对象引用;

    2. 将对象的引用保存在volatile或AtomicReference上

    3. 将对象的引用保存到某个正确构造对象的final类型上

    4. 将对象保存在一个锁的范围内.

    安全访问:

    1. 线程封闭

    2. 只读共享

    3. 线程安全共享, 该发布对象内部的访问方式是线程安全的, 就不需要外部同步了

    4. 保护对象, 发布可变对象的对象通过限制外界的访问, 指定访问可变对象的接口.

    static List<String> arrayList = new ArrayList<>();这样已经符合了安全发布的第一条
    那么就要保证安全访问了, 由于list肯定不能安全访问的前三种情况, 那么只能依靠在发布对象时,限制外界的访问, 也就是加锁.

    Antwort
    0
  • PHP中文网

    PHP中文网2017-04-18 10:10:52

    可以按照题主的要求实现,不过这种需求的实现很诡异。

        private static void test1(final int i) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (arrayList) {
                    while (arrayList.size() != i) {
                        try {
                            arrayList.wait();
                        } catch (InterruptedException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }
                    }
                    arrayList.add(i, i + "position");
                    arrayList.notifyAll();
                }
            }
        }).start();
    }
    

    除了这种方式,还可以通过join和传入countdownlatch来实现.如果真的想像题主这样子的话,还不如不用多线程

    Antwort
    0
  • 天蓬老师

    天蓬老师2017-04-18 10:10:52

    用线程池的invokeAll方法,可以保证结果的顺序和传入参数的顺序一致

    Antwort
    0
  • 黄舟

    黄舟2017-04-18 10:10:52

    public static void main(String[] args) {
            ExecutorService exec = Executors.newFixedThreadPool(10);
            
            List<Callable<Integer>> list = new ArrayList<>();
            
            for (int i = 0; i < 10; i++) {
                list.add(newTask(i));
            }
            
            try {
                for (Future<Integer> future : exec.invokeAll(list)) {
                    try {
                        System.out.println(future.get());
                    } catch (ExecutionException e) {
                        e.printStackTrace();
                    }
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            exec.shutdown();
        }
        
        static Callable<Integer> newTask(final int t) {
            return new Callable<Integer>() {
                @Override
                public Integer call() throws Exception {
                    System.out.println("newTask: " + t);
                    try {
                        Thread.sleep((10 - t) * 1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    return t;
                }
            }
        }

    Antwort
    0
  • StornierenAntwort