移动端开发过程中,会出现 进程 和 线程的概念,以及多线程中 线程安全 的问题。
进程 和 线程
进程: APP 启动时,应用会启动一个新的 Linux 进程, 一个app内可以有多个进程,进程之间不共享数据。
线程: 1个进程中可以包含多个线程,线程之间数据共享。
多线程 (主线程 和 工作线程)
启动应用时,系统会为该应用创建一个称为“main”(主线程)的执行线程,在和用户交互时,主线程不允许做耗时任务,所以需要后台线程处理这些耗时任务。 这样在应用中就会存在很多的线程,也就是大家说的多线程。
多线程使用示例:
public void onClick(View v) {
new Thread(new Runnable() {
public void run() {
// a potentially time consuming task
final Bitmap bitmap =
processBitMap("image.png");
imageView.post(new Runnable() {
public void run() {
imageView.setImageBitmap(bitmap);
}
});
}
}).start();
}
//常用的还有使用线程池
public static final ExecutorService sTheadPoolExecutor
= new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE,
TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(30),
new ThreadPoolExecutor.DiscardOldestPolicy());
private ExecutorService grayThreadPool = Executors.newSingleThreadExecutor();
线程安全
多线程之间,因为共享应用数据。所以在多个线程同时访问数据时,也就会引入线程安全的问题。
多线程安全要解决的问题是,不同线程访问同一数据时的数据安全问题。
解决线程安全的常用方法是增加 synchronized
关键字.
synchronized
使用示例:
//synchronized 加在方法上
private synchronized void setNewValue(int a, int b) {
x = a;
y = b;
}
//synchronized 加在方法内的代码块上
private void setNewValue(int a, int b) {
synchronized (monitor1) {
x = a;
y = b;
}
}
1.synchronized
保证方法内部或者代码块内部(数据)的互斥访问
. 也就是同一时间,只能由1个线程来访问synchronized
内的数据
2.synchronized
保证线程之间对监视资源的数据同步
. 也就是任何线程在获取到 Monitor 后的第⼀时 间,会先将共享内存中的数据复制到⾃自⼰己的缓存中;任何线程在释放 Monitor 的第⼀时间,会先将缓存中的数据复制到共享内存中.
线程数据同步安全中,volatile
关键字也是比较常用的, volatile
关键字能够保证可见性,被volatile修饰的变量,在一个线程中被改变时会立刻同步到主内存中,而另一个线程在操作这个变量时都会先从主内存更新这个变量的值
volatile
使用示例:
private volatile static Singleton mSingleton = null;
private Singleton () {}
public static Singleton getInstance() {
if (mSingleton == null) {
synchronized (Singleton.class) {
if (mSingleton == null) {
mSingleton = new Singleton();
}
}
}
return mSingleton;
}
Lock / ReentrantReadWriteLock
:
Lock
也是给代码加锁的一种方式, 常用的ReentrantReadWriteLock
可以更精细化的管理共享的内存资源。 需要特别注意的是,Lock
的加锁形式需要开发者手动释放锁
private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
private ReentrantReadWriteLock.ReadLock readLock = lock.readLock();
private ReentrantReadWriteLock.WriteLock writeLock = lock.writeLock();
private void setValue(int newValue) {
writeLock.lock();
try {
a = newValue;
} finally {
writeLock.unlock();
}
}
private void print() {
readLock.lock();
try {
System.out.println("values: " + a);
} finally {
readLock.unlock();
}
}
END!
网友评论