English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
A implementação do ArrayList da interface List com arrays de tamanho variável. Implementa todas as operações opcionais de lista e permite todos os elementos, incluindo null. Além de implementar a interface List, esse tipo fornece alguns métodos para operar o tamanho do array interno usado para armazenar a lista. (Esse tipo é aproximadamente equivalente ao Vector, exceto que esse é não sincronizado.) As operações size, isEmpty, get, set, iterator e listIterator executam em tempo constante. A operação add roda em tempo constante distribuído, o que significa que adicionar n elementos requer tempo O(n). Todas as outras operações rodam em tempo linear (em termos gerais). Comparado com os fatores constantes usados na implementação LinkedList, os fatores constantes dessa implementação são menores. Cada instância de ArrayList tem uma capacidade. A capacidade é o tamanho do array usado para armazenar os elementos da lista. Sempre é pelo menos igual ao tamanho da lista. À medida que elementos são adicionados ao ArrayList, sua capacidade também aumenta automaticamente. Não são especificados os detalhes da estratégia de crescimento, porque não é apenas a adição de elementos que traz um custo de tempo constante distribuído. Antes de adicionar muitos elementos, o aplicativo pode usar a operação ensureCapacity para aumentar a capacidade da instância de ArrayList. Isso pode reduzir o número de redistribuições incrementais.
Atenção, essa implementação não é sincronizada.
Se várias threads acessarem simultaneamente uma instância de ArrayList e pelo menos uma delas fizer alterações estruturais na lista, é necessário manter a sincronização externa. (Alterações estruturais significam qualquer operação de adição ou exclusão de um ou mais elementos, ou ajuste explícito do tamanho do array subjacente; ajustar apenas o valor dos elementos não é uma alteração estrutural.) Isso geralmente é feito através de operações de sincronização no objeto que naturalmente encapsula a lista. Se não houver tal objeto, deve-se usar o método Collections.synchronizedList para 'embalar' a lista. Isso é melhor feito na criação, para evitar acessos inesperados não sincronizados à lista:
Listlist=Collections.synchronizedList(newArrayList(...));
Os métodos iterator e listIterator deste tipo retornam iteradores de falha rápida: após a criação do iterador, a menos que seja feita alguma modificação estrutural na lista por meio dos métodos remove ou add do próprio iterador, qualquer modificação na lista em qualquer momento de qualquer maneira lançará ConcurrentModificationException. Portanto, diante de modificações concorrentes, o iterador falhará rapidamente, em vez de correr o risco de comportamento incerto em algum momento futuro indeterminado.
Atenção, o comportamento de falha rápida do iterador não pode ser garantido, porque geralmente é impossível fazer qualquer garantia rígida sobre a ocorrência de modificações concorrentes. O iterador de falha rápida fará o maior esforço para lançar ConcurrentModificationException. Portanto, escrever um programa que depende dessa exceção é uma prática errada: o comportamento de falha rápida do iterador deve ser usado apenas para detectar bugs.
Como mostrado acima, agora estamos criando um conjunto list, uma thread para operações de escrita no conjunto e outra para operações de exclusão
import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Random; public class MyArrayList { /** * Criar uma lista, uma thread para escrever e outra para ler os iteradores retornados por iterator e listIterator são rápidos quebrados */ public void readWrite() { List<Integer> nums = new ArrayList<Integer>(); List<Integer> synNums = Collections.synchronizedList(nums); //Iniciar a thread de escrita new WriteListThread(synNums).start(); //Iniciar a thread de exclusão new DeleteListThread(synNums).start(); } public static void main(String[] args) { new MyArrayList().readWrite(); } } class WriteListThread extends Thread { private List<Integer> nums; public WriteListThread(List<Integer> nums) { super(“WriteListThread”); this.nums = nums; } // Continuar escrevendo elementos1 public void run() { while (true) { nums.add(new Random().nextint(1000)); System.out.println(Thread.currentThread().getName()); } } } class DeleteListThread extends Thread { private List<Integer> nums; public DeleteListThread(List<Integer> nums) { super(“DeleteListThread”); this.nums = nums; } // Remover o primeiro elemento public void run() { while (true) { try{ System.out.println(Thread.currentThread().getName()+:”+nums.remove(0)); } catch(Exception e){ continue ; } } } }
Através de List<Integer> synNums = Collections.synchronizedList(nums); podemos sincronizar operações atômicas, mas por que o exemplo oficial da API requer a adição manual de sincronização?
List list = Collections.synchronizedList(new ArrayList()); synchronized(list) { Iterator i = list.iterator(); // Deve estar dentro de um bloco sincronizado while (i.hasNext()) foo(i.next()); }
Verifique o código-fonte da Collections.synchronizedList
SynchronizedCollection(Collection<E> c) { if (c==null) throw new NullPointerException(); this.c = c; mutex = this; }
import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Random; public class MyArrayList { /** * Criar uma lista, uma thread para escrever e outra para ler os iteradores retornados por iterator e listIterator são rápidos quebrados */ public void readWrite() { List<Integer> nums = new ArrayList<Integer>(); List<Integer> synNums = Collections.synchronizedList(nums); //Iniciar a thread de escrita new WriteListThread(synNums).start(); //Iniciar a thread de exclusão new DeleteListThread(synNums).start(); } public static void main(String[] args) { new MyArrayList().readWrite(); } } class WriteListThread extends Thread { private List<Integer> nums; public WriteListThread(List<Integer> nums) { super("WriteListThread"); this.nums = nums; } // Continuar escrevendo elementos1 public void run() { while (true) { nums.add(new Random().nextint(1000)); System.out.println(Thread.currentThread().getName()); } } } class DeleteListThread extends Thread { private List<Integer> nums; public DeleteListThread(List<Integer> nums) { super("DeleteListThread"); this.nums = nums; } // Remover o primeiro elemento public void run() { while (true) { try{ System.out.println(Thread.currentThread().getName()+":"+nums.remove(0)); } catch(Exception e){ continue ; } } } }
Para operações de sincronização de conjunto, além de usar as ferramentas de embalagem sincronizadas de Collections, os usuários ainda precisam sincronizar manualmente operações não atômicas
Como mostrado a seguir, adicionar uma thread para ler a coleção
class ReadListThread extends Thread { private List<Integer> nums; public ReadListThread(List<Integer> nums) {}} super(“ReadListThread”); this.nums = nums; } // Ler continuamente elementos, operação não atômica, precisa adicionar manualmente o bloqueio public void run() { while (true) { //Dormir, passar o bloqueio para outra thread try { Thread.sleep(1000); } catch (InterruptedException e1) { e1.printStackTrace(); } synchronized (nums) { if (nums.size() > 100) { Iterator<Integer> iter = nums.iterator(); while (iter.hasNext()) { System.out.println(Thread.currentThread().getName() + :” + iter.next()); ; } } else{ try { nums.wait(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } } } }
Resumo
Isso é tudo sobre a explicação detalhada do código de sincronização de threads da estrutura de coleções Java neste artigo. Espero que ajude a todos. Os amigos interessados podem continuar a ler outros tópicos relacionados neste site. Se houver点什么不足之处,请留言指出。感谢朋友们对本站的支持!
Declaração: O conteúdo deste artigo é extraído da Internet, pertence ao respectivo proprietário. O conteúdo é contribuído e carregado voluntariamente pelos usuários da Internet. Este site não possui direitos de propriedade, não foi editado manualmente e não assume responsabilidade por eventuais responsabilidades legais. Se encontrar conteúdo suspeito de violação de direitos autorais, envie um e-mail para: notice#oldtoolbag.com (ao enviar e-mail, substitua # por @ para denunciar e forneça provas relevantes. Aos nossos esforços, o conteúdo suspeito de violação de direitos autorais será removido imediatamente. Se encontrar conteúdo suspeito de violação de direitos autorais, envie um e-mail para: notice#w