【面试专栏】ArrayList 非线程安全案例并提供三种解决方案
1. 复现问题
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
/**
* 复现问题
*
* @author CL
*
*/
public class RecurrenceProblem {
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
// 启动30个线程
for (int i = 0; i < 30; i++) {
new Thread(() -> {
list.add(UUID.randomUUID().toString().substring(0, 8));
System.out.println(list);
}, String.valueOf(i)).start();
}
}
}
运行结果:
[42251c59]
[42251c59, 5839198b]
[42251c59, 5839198b, 1283d17b]
[42251c59, 5839198b, 1283d17b, 01fce852]
[42251c59, 5839198b, 1283d17b, 01fce852, 857eb6d1]
[42251c59, 5839198b, 1283d17b, 01fce852, 857eb6d1, eb874846]
[42251c59, 5839198b, 1283d17b, 01fce852, 857eb6d1, eb874846, 7cfa654c]
[42251c59, 5839198b, 1283d17b, 01fce852, 857eb6d1, eb874846, 7cfa654c, 794c24d5]
[42251c59, 5839198b, 1283d17b, 01fce852, 857eb6d1, eb874846, 7cfa654c, 794c24d5, 68a415a7, f51c911a]
[42251c59, 5839198b, 1283d17b, 01fce852, 857eb6d1, eb874846, 7cfa654c, 794c24d5, 68a415a7]
[42251c59, 5839198b, 1283d17b, 01fce852, 857eb6d1, eb874846, 7cfa654c, 794c24d5, 68a415a7, f51c911a, 9f99c03a]
[42251c59, 5839198b, 1283d17b, 01fce852, 857eb6d1, eb874846, 7cfa654c, 794c24d5, 68a415a7, f51c911a, 9f99c03a, 84213b11]
[42251c59, 5839198b, 1283d17b, 01fce852, 857eb6d1, eb874846, 7cfa654c, 794c24d5, 68a415a7, f51c911a, 9f99c03a, 84213b11, b1d1c583]
[42251c59, 5839198b, 1283d17b, 01fce852, 857eb6d1, eb874846, 7cfa654c, 794c24d5, 68a415a7, f51c911a, 9f99c03a, 84213b11, b1d1c583, 04ecf6c3]
[42251c59, 5839198b, 1283d17b, 01fce852, 857eb6d1, eb874846, 7cfa654c, 794c24d5, 68a415a7, f51c911a, 9f99c03a, 84213b11, b1d1c583, 04ecf6c3, 4d16693d, 65a4715e]
[42251c59, 5839198b, 1283d17b, 01fce852, 857eb6d1, eb874846, 7cfa654c, 794c24d5, 68a415a7, f51c911a, 9f99c03a, 84213b11, b1d1c583, 04ecf6c3, 4d16693d]
[42251c59, 5839198b, 1283d17b, 01fce852, 857eb6d1, eb874846, 7cfa654c, 794c24d5, 68a415a7, f51c911a, 9f99c03a, 84213b11, b1d1c583, 04ecf6c3, 4d16693d, 65a4715e, e968aa23]
[42251c59, 5839198b, 1283d17b, 01fce852, 857eb6d1, eb874846, 7cfa654c, 794c24d5, 68a415a7, f51c911a, 9f99c03a, 84213b11, b1d1c583, 04ecf6c3, 4d16693d, 65a4715e, e968aa23, b60db864]
[42251c59, 5839198b, 1283d17b, 01fce852, 857eb6d1, eb874846, 7cfa654c, 794c24d5, 68a415a7, f51c911a, 9f99c03a, 84213b11, b1d1c583, 04ecf6c3, 4d16693d, 65a4715e, e968aa23, b60db864, fb3a9828, 3fd4f004]
[42251c59, 5839198b, 1283d17b, 01fce852, 857eb6d1, eb874846, 7cfa654c, 794c24d5, 68a415a7, f51c911a, 9f99c03a, 84213b11, b1d1c583, 04ecf6c3, 4d16693d, 65a4715e, e968aa23, b60db864, fb3a9828]
[42251c59, 5839198b, 1283d17b, 01fce852, 857eb6d1, eb874846, 7cfa654c, 794c24d5, 68a415a7, f51c911a, 9f99c03a, 84213b11, b1d1c583, 04ecf6c3, 4d16693d, 65a4715e, e968aa23, b60db864, fb3a9828, 3fd4f004, 333308f6]
[42251c59, 5839198b, 1283d17b, 01fce852, 857eb6d1, eb874846, 7cfa654c, 794c24d5, 68a415a7, f51c911a, 9f99c03a, 84213b11, b1d1c583, 04ecf6c3, 4d16693d, 65a4715e, e968aa23, b60db864, fb3a9828, 3fd4f004, 333308f6, 7143a717, 9ba40ac6]
[42251c59, 5839198b, 1283d17b, 01fce852, 857eb6d1, eb874846, 7cfa654c, 794c24d5, 68a415a7, f51c911a, 9f99c03a, 84213b11, b1d1c583, 04ecf6c3, 4d16693d, 65a4715e, e968aa23, b60db864, fb3a9828, 3fd4f004, 333308f6, 7143a717, 9ba40ac6, 06ae20ed]
[42251c59, 5839198b, 1283d17b, 01fce852, 857eb6d1, eb874846, 7cfa654c, 794c24d5, 68a415a7, f51c911a, 9f99c03a, 84213b11, b1d1c583, 04ecf6c3, 4d16693d, 65a4715e, e968aa23, b60db864, fb3a9828, 3fd4f004, 333308f6, 7143a717, 9ba40ac6, 06ae20ed, a8aa4fea]
Exception in thread "21" [42251c59, 5839198b, 1283d17b, 01fce852, 857eb6d1, eb874846, 7cfa654c, 794c24d5, 68a415a7, f51c911a, 9f99c03a, 84213b11, b1d1c583, 04ecf6c3, 4d16693d, 65a4715e, e968aa23, b60db864, fb3a9828, 3fd4f004, 333308f6, 7143a717, 9ba40ac6, 06ae20ed, a8aa4fea, 0d3b8cf8]
[42251c59, 5839198b, 1283d17b, 01fce852, 857eb6d1, eb874846, 7cfa654c, 794c24d5, 68a415a7, f51c911a, 9f99c03a, 84213b11, b1d1c583, 04ecf6c3, 4d16693d, 65a4715e, e968aa23, b60db864, fb3a9828, 3fd4f004, 333308f6, 7143a717, 9ba40ac6, 06ae20ed, a8aa4fea, 0d3b8cf8, 6fb56487]
[42251c59, 5839198b, 1283d17b, 01fce852, 857eb6d1, eb874846, 7cfa654c, 794c24d5, 68a415a7, f51c911a, 9f99c03a, 84213b11, b1d1c583, 04ecf6c3, 4d16693d, 65a4715e, e968aa23, b60db864, fb3a9828, 3fd4f004, 333308f6, 7143a717, 9ba40ac6, 06ae20ed, a8aa4fea, 0d3b8cf8, 6fb56487, b9fb25b8]
java.util.ConcurrentModificationException
[42251c59, 5839198b, 1283d17b, 01fce852, 857eb6d1, eb874846, 7cfa654c, 794c24d5, 68a415a7, f51c911a, 9f99c03a, 84213b11, b1d1c583, 04ecf6c3, 4d16693d, 65a4715e, e968aa23, b60db864, fb3a9828, 3fd4f004, 333308f6, 7143a717, 9ba40ac6, 06ae20ed, a8aa4fea, 0d3b8cf8, 6fb56487, b9fb25b8, 3b98b513]
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:901)
at java.util.ArrayList$Itr.next(ArrayList.java:851)
at java.util.AbstractCollection.toString(AbstractCollection.java:461)
at java.lang.String.valueOf(String.java:2994)
at java.io.PrintStream.println(PrintStream.java:821)
at com.c3stones.demo.RecurrenceProblem.lambda$0(RecurrenceProblem.java:22)
at java.lang.Thread.run(Thread.java:745)
[42251c59, 5839198b, 1283d17b, 01fce852, 857eb6d1, eb874846, 7cfa654c, 794c24d5, 68a415a7, f51c911a, 9f99c03a, 84213b11, b1d1c583, 04ecf6c3, 4d16693d, 65a4715e, e968aa23, b60db864, fb3a9828, 3fd4f004, 333308f6, 7143a717, 9ba40ac6, 06ae20ed, a8aa4fea, 0d3b8cf8, 6fb56487, b9fb25b8, 3b98b513, 83bd3f54]
出现:java.util.ConcurrentModificationException异常
2. 原因剖析
java.util.ConcurrentModificationException即并发修改异常。
查看ArrayList.add(...)源码:
/**
* Appends the specified element to the end of this list.
*
* @param e element to be appended to this list
* @return <tt>true</tt> (as specified by {@link Collection#add})
*/
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
发现并没有对该方法加锁,因此在并发修改时,必然是线程不安全的,则抛出java.util.ConcurrentModificationException异常。
3. 解决方案
- Vector
使用Vector代替ArrayList。
查看Vector.add(...)源码:
/**
* Appends the specified element to the end of this Vector.
*
* @param e element to be appended to this Vector
* @return {@code true} (as specified by {@link Collection#add})
* @since 1.2
*/
public synchronized boolean add(E e) {
modCount++;
ensureCapacityHelper(elementCount + 1);
elementData[elementCount++] = e;
return true;
}
可以看到add方法中使用synchronized实现同步。代码修改为:
import java.util.List;
import java.util.UUID;
import java.util.Vector;
/**
* 解决方案01-Vector
*
* @author CL
*
*/
public class Solution01 {
public static void main(String[] args) {
List<String> list = new Vector<String>();
// 启动30个线程
for (int i = 0; i < 30; i++) {
new Thread(() -> {
list.add(UUID.randomUUID().toString().substring(0, 8));
System.out.println(list);
}, String.valueOf(i)).start();
}
}
}
运行结果:
[759f9961]
[759f9961, ff871e85, 4a3939a2, 59e796cf, cf4dfbda, bbc62489, 439941c6]
[759f9961, ff871e85, 4a3939a2, 59e796cf, cf4dfbda, bbc62489, 439941c6, 7a003645]
[759f9961, ff871e85, 4a3939a2, 59e796cf, cf4dfbda, bbc62489, 439941c6, 7a003645, fc224a2b]
[759f9961, ff871e85, 4a3939a2, 59e796cf, cf4dfbda, bbc62489, 439941c6, 7a003645, fc224a2b, f52573e5, 1144e6c3]
[759f9961, ff871e85, 4a3939a2, 59e796cf, cf4dfbda, bbc62489, 439941c6, 7a003645, fc224a2b, f52573e5, 1144e6c3, 4de11c35]
[759f9961, ff871e85, 4a3939a2, 59e796cf, cf4dfbda, bbc62489, 439941c6, 7a003645, fc224a2b, f52573e5, 1144e6c3, 4de11c35, ba2e2d82, 95d9f85e]
[759f9961, ff871e85, 4a3939a2, 59e796cf, cf4dfbda, bbc62489]
[759f9961, ff871e85, 4a3939a2, 59e796cf, cf4dfbda, bbc62489, 439941c6, 7a003645, fc224a2b, f52573e5, 1144e6c3, 4de11c35, ba2e2d82, 95d9f85e, d4cfdf23]
[759f9961, ff871e85, 4a3939a2, 59e796cf, cf4dfbda, bbc62489, 439941c6, 7a003645, fc224a2b, f52573e5, 1144e6c3, 4de11c35, ba2e2d82, 95d9f85e, d4cfdf23, 90dd544b]
[759f9961, ff871e85, 4a3939a2, 59e796cf, cf4dfbda, bbc62489, 439941c6, 7a003645, fc224a2b, f52573e5, 1144e6c3, 4de11c35, ba2e2d82, 95d9f85e, d4cfdf23, 90dd544b, 59e75219]
[759f9961, ff871e85, 4a3939a2, 59e796cf, cf4dfbda]
[759f9961, ff871e85, 4a3939a2, 59e796cf]
[759f9961, ff871e85, 4a3939a2]
[759f9961, ff871e85]
[759f9961, ff871e85, 4a3939a2, 59e796cf, cf4dfbda, bbc62489, 439941c6, 7a003645, fc224a2b, f52573e5, 1144e6c3, 4de11c35, ba2e2d82, 95d9f85e, d4cfdf23, 90dd544b, 59e75219, a3787684, fb5cf421]
[759f9961, ff871e85, 4a3939a2, 59e796cf, cf4dfbda, bbc62489, 439941c6, 7a003645, fc224a2b, f52573e5, 1144e6c3, 4de11c35, ba2e2d82, 95d9f85e, d4cfdf23, 90dd544b, 59e75219, a3787684, fb5cf421, 9ca37cea]
[759f9961, ff871e85, 4a3939a2, 59e796cf, cf4dfbda, bbc62489, 439941c6, 7a003645, fc224a2b, f52573e5, 1144e6c3, 4de11c35, ba2e2d82, 95d9f85e, d4cfdf23, 90dd544b, 59e75219, a3787684]
[759f9961, ff871e85, 4a3939a2, 59e796cf, cf4dfbda, bbc62489, 439941c6, 7a003645, fc224a2b, f52573e5, 1144e6c3, 4de11c35, ba2e2d82]
[759f9961, ff871e85, 4a3939a2, 59e796cf, cf4dfbda, bbc62489, 439941c6, 7a003645, fc224a2b, f52573e5, 1144e6c3, 4de11c35, ba2e2d82, 95d9f85e, d4cfdf23, 90dd544b, 59e75219, a3787684, fb5cf421, 9ca37cea, 8cbe36f6, 62494d83]
[759f9961, ff871e85, 4a3939a2, 59e796cf, cf4dfbda, bbc62489, 439941c6, 7a003645, fc224a2b, f52573e5, 1144e6c3, 4de11c35, ba2e2d82, 95d9f85e, d4cfdf23, 90dd544b, 59e75219, a3787684, fb5cf421, 9ca37cea, 8cbe36f6, 62494d83, 846001e0, ec1efeaf]
[759f9961, ff871e85, 4a3939a2, 59e796cf, cf4dfbda, bbc62489, 439941c6, 7a003645, fc224a2b, f52573e5]
[759f9961, ff871e85, 4a3939a2, 59e796cf, cf4dfbda, bbc62489, 439941c6, 7a003645, fc224a2b, f52573e5, 1144e6c3, 4de11c35, ba2e2d82, 95d9f85e, d4cfdf23, 90dd544b, 59e75219, a3787684, fb5cf421, 9ca37cea, 8cbe36f6, 62494d83, 846001e0, ec1efeaf, 12155931]
[759f9961, ff871e85, 4a3939a2, 59e796cf, cf4dfbda, bbc62489, 439941c6, 7a003645, fc224a2b, f52573e5, 1144e6c3, 4de11c35, ba2e2d82, 95d9f85e, d4cfdf23, 90dd544b, 59e75219, a3787684, fb5cf421, 9ca37cea, 8cbe36f6, 62494d83, 846001e0, ec1efeaf, 12155931, 12e61627]
[759f9961, ff871e85, 4a3939a2, 59e796cf, cf4dfbda, bbc62489, 439941c6, 7a003645, fc224a2b, f52573e5, 1144e6c3, 4de11c35, ba2e2d82, 95d9f85e, d4cfdf23, 90dd544b, 59e75219, a3787684, fb5cf421, 9ca37cea, 8cbe36f6, 62494d83, 846001e0]
[759f9961, ff871e85, 4a3939a2, 59e796cf, cf4dfbda, bbc62489, 439941c6, 7a003645, fc224a2b, f52573e5, 1144e6c3, 4de11c35, ba2e2d82, 95d9f85e, d4cfdf23, 90dd544b, 59e75219, a3787684, fb5cf421, 9ca37cea, 8cbe36f6]
[759f9961, ff871e85, 4a3939a2, 59e796cf, cf4dfbda, bbc62489, 439941c6, 7a003645, fc224a2b, f52573e5, 1144e6c3, 4de11c35, ba2e2d82, 95d9f85e, d4cfdf23, 90dd544b, 59e75219, a3787684, fb5cf421, 9ca37cea, 8cbe36f6, 62494d83, 846001e0, ec1efeaf, 12155931, 12e61627, fa205c82]
[759f9961, ff871e85, 4a3939a2, 59e796cf, cf4dfbda, bbc62489, 439941c6, 7a003645, fc224a2b, f52573e5, 1144e6c3, 4de11c35, ba2e2d82, 95d9f85e, d4cfdf23, 90dd544b, 59e75219, a3787684, fb5cf421, 9ca37cea, 8cbe36f6, 62494d83, 846001e0, ec1efeaf, 12155931, 12e61627, fa205c82, 04726e78]
[759f9961, ff871e85, 4a3939a2, 59e796cf, cf4dfbda, bbc62489, 439941c6, 7a003645, fc224a2b, f52573e5, 1144e6c3, 4de11c35, ba2e2d82, 95d9f85e, d4cfdf23, 90dd544b, 59e75219, a3787684, fb5cf421, 9ca37cea, 8cbe36f6, 62494d83, 846001e0, ec1efeaf, 12155931, 12e61627, fa205c82, 04726e78, 0ee9c3d5]
[759f9961, ff871e85, 4a3939a2, 59e796cf, cf4dfbda, bbc62489, 439941c6, 7a003645, fc224a2b, f52573e5, 1144e6c3, 4de11c35, ba2e2d82, 95d9f85e, d4cfdf23, 90dd544b, 59e75219, a3787684, fb5cf421, 9ca37cea, 8cbe36f6, 62494d83, 846001e0, ec1efeaf, 12155931, 12e61627, fa205c82, 04726e78, 0ee9c3d5, 097c1d4e]
从运行结果可以看出,已经解决了问题。但是查看Vector类说明和ArrayList类说明:
/*
* @author Lee Boynton
* @author Jonathan Payne
* @see Collection
* @see LinkedList
* @since JDK1.0
*/
public class Vector<E>
extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{
...
}
/*
* @author Josh Bloch
* @author Neal Gafter
* @see Collection
* @see List
* @see LinkedList
* @see Vector
* @since 1.2
*/
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{
...
}
可以看出,Vector是JDK1.0时出现的,ArrayList是JDK1.2出现的。因此,官方肯定不建议使用Vector来解决此问题。
- Collections
使用Collections工具类提供的方法来避免ArrayList出现的并发修改问题。代码修改为:
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
/**
* 解决方案02-Collections
*
* @author CL
*
*/
public class Solution02 {
public static void main(String[] args) {
List<String> list = Collections.synchronizedList(new ArrayList<String>());
// 启动30个线程
for (int i = 0; i < 30; i++) {
new Thread(() -> {
list.add(UUID.randomUUID().toString().substring(0, 8));
System.out.println(list);
}, String.valueOf(i)).start();
}
}
}
Set、Map在创建实例时也可以使用此方式:
Set<String> set = Collections.synchronizedSet(new HashSet<String>());
Map<Integer, String> map = Collections.synchronizedMap(new HashMap<>());
- CopyOnWrite
CopyOnWrite写时复制。CopyOnWriteArrayList.add(...)方法:
/**
* Appends the specified element to the end of this list.
*
* @param e element to be appended to this list
* @return {@code true} (as specified by {@link Collection#add})
*/
public boolean add(E e) {
final ReentrantLock lock = this.lock;
lock.lock();
try {
Object[] elements = getArray();
int len = elements.length;
Object[] newElements = Arrays.copyOf(elements, len + 1);
newElements[len] = e;
setArray(newElements);
return true;
} finally {
lock.unlock();
}
}
可以看出在方法进入时加锁。先创建一个比之前长度大1的数组,并在末尾添加元素,最后再将源容器指向新的容器。这样的好处是源容器不会添加任何元素,这也是一种读写分离的思想。
代码修改为:
import java.util.List;
import java.util.UUID;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* 解决方案03-CopyOnWrite
*
* @author CL
*
*/
public class Solution03 {
public static void main(String[] args) {
List<String> list = new CopyOnWriteArrayList<String>();
// 启动30个线程
for (int i = 0; i < 30; i++) {
new Thread(() -> {
list.add(UUID.randomUUID().toString().substring(0, 8));
System.out.println(list);
}, String.valueOf(i)).start();
}
}
}
Set、Map在创建实例时也可以使用此方式:
Set<String> set = new CopyOnWriteArraySet<String>();
Map<Integer, String> map = new ConcurrentHashMap<Integer, String>();
4. 项目地址
【面试专栏】ArrayList 非线程安全案例并提供三种解决方案的更多相关文章
- Vector线程安全,ArrayList非线程安全
http://baijiahao.baidu.com/s?id=1638844080997170869&wfr=spider&for=pc Vector线程安全,ArrayList非线 ...
- net异步线程获取返回值的三种方式
方式一:endInvoke using System; using System.Collections.Generic; using System.Text; using System.Thread ...
- QThread多线程编程经典案例分析(三种方法,解释了为什么使用moveToThread的根本原因,即为了避免调用QThread::exec() )
传统的图形界面应用程序都只有一个线程执行,并且一次执行一个操作.如果用户调用一个比较耗时的操作,就会冻结界面响应. 一个解决方法是按照事件处理的思路: 调用 Void QApplication::pr ...
- Android:在子线程中更新UI的三种方式
①使用Activity中的runOnUiThread(Runnable) ②使用Handler中的post(Runnable) 在创建Handler对象时,必须先通过Context的getMainLo ...
- Java经典案例之用三种方法求1~100以内素数之和
素数,不能被除了1和本身以外整除的数被称为素数.接下来我用三种方式求得1~100以内素数. 方式一 外层每循环一次,内层就计算出这个数有几个因子,我们都知道素数的因子只有两个,所以如果个数为2就加进总 ...
- 面试必备:Java线程池解析
前言 掌握线程池是后端程序员的基本要求,相信大家求职面试过程中,几乎都会被问到有关于线程池的问题.我在网上搜集了几道经典的线程池面试题,并以此为切入点,谈谈我对线程池的理解.如果有哪里理解不正确,非常 ...
- 线程安全 Vs 非线程安全
线程安全:多线程访问时,采用了加锁机制,当一个线程读取数据时,其他线程不能访问直到该线程读取完毕.不会出现数据不一致或者脏数据. 非线程安全:不提供数据保护,可能出现其他线程访问时更改数据而该线程得到 ...
- 集合不安全之 ArrayList及其三种解决方案【CopyOnWriteArrayList 、synchronizedList、Vector 】
@ 目录 一.前言 二.为什么线程不安全 三.解决方案一CopyOnWriteArrayList (推荐,读多写少场景) 四.Collections.synchronizedList(加锁) 五.Ve ...
- Java并发编程:Java创建线程的三种方式
目录 引言 创建线程的三种方式 一.继承Thread类 二.实现Runnable接口 三.使用Callable和Future创建线程 三种方式的对比 引言 在日常开发工作中,多线程开发可以说是必备技能 ...
随机推荐
- java中高级面试利器(boot,cloud,vue前后端提升)
https://github.com/Snailclimb/JavaGuide Java知识大全(面试) https://github.com/doocs/advanced-java Java工 ...
- 建议收藏!2020阿里面试题(JVM+Spring Cloud+微服务)上
前言 对于大厂面试,我想要强调的一点就是心态真的很重要,是决定你在面试过程中发挥的关键,若不能正常发挥,很可能就因为一个小失误与offer失之交臂,所以一定要重视起来.另外提醒一点,充分复习,是消除你 ...
- java面试官最爱问的垃圾回收机制,这位阿里P7大佬分析的属实到位
前言 JVM 内存模型一共包括三个部分: 堆 ( Java代码可及的 Java堆 和 JVM自身使用的方法区). 栈 ( 服务Java方法的虚拟机栈 和 服务Native方法的本地方法栈 ) 保证程序 ...
- 去年去阿里面试,被问到ArrayList和LinkedList,我是这样回答的!
前言 在一开始基础面的时候,很多面试官可能会问List集合一些基础知识,比如: ArrayList默认大小是多少,是如何扩容的? ArrayList和LinkedList的底层数据结构是什么? Arr ...
- Camtasia中对录制视频进行编辑——交互性
随着新媒体的广泛发展,视频处理的需要也逐渐变得越来越大,很多人都不知道市场上的哪款软件是比较符合大众需要的.有的软件功能写的天花乱坠,但是实际操作确很难.并不符合大众的简单需求. 今天我便给大家推荐一 ...
- appium每次运行不初始化
最近测试公司软件遇到一个问题,每次运行Appium测试代码,打开软件都是初始化,每次的新手教程以及无法记住密码一堆问题,导致效率很低,而且定位有时候出问题. 先看初始化的代码 1 from appiu ...
- LIKE 运算符
运算符用于执行程序代码运算,会针对一个以上操作数项目来进行运算.例如:2+3,其操作数是2和3,而运算符则是"+".在vb2005中运算符大致可以分为5种类型:算术运算符.连接运算 ...
- Contest 984
A 先手取最大,后手取最小,答案就是第 \(\left\lceil\frac{n}{2}\right\rceil\) 小的数. 用 nth_element 可以做到 \(O\left(n\right) ...
- go特性-数组与切片
数组: 复制传递(不要按照c/c++的方式去理解,c/c++中数组是引用传递),定长 切片: 引用传递,底层实现是3个字段 array(数组) + len(长度) +cap(容量) type slic ...
- mfc c++优化
1.不住求精度时,尽量使用单精度浮点型2.使用32位数据类型3.使用有符号和无符号整型: 前提:无需考虑正负时 double x; int i; x = i; 使用有符号:unsigned int i ...