JasonWang's Blog

Java并发编程之同步

在单一线程执行的情况下,并不用考虑任何数据一致性与同步等问题,但到了多个线程执行的情况下,共享数据的同步就显得至关重要了。比如有一个银行账户的操作问题(例子来自Wikipedia),现在有两个线程A与B共享一个账户变量balance,这个提款的操作有两个部分,首先需要判定提款数目是否小于当前账户存款,记为s1;如果该条件满足,则从账户中提取资金,记为s2。假定开始时账户balance=600,现在A调用withdraw(200),B调用withdraw(500),如果两个线程A与B调用时,s1都发生在s2之前,则两个线程都可以进入判定条件,提取相应的资金,而实际的存款是小于两个线程需要提取的资金的。

1
2
3
4
5
6
7
8
9
10
11
12
13

bool withdraw(int withdrawal)
{

if (balance >= withdrawal) // --> s1
{

balance -= withdrawal; // --> s2
return true;
}
return false;
}

这种线程之间共享资源的一致性同步问题在并发编程中十分常见,通常被称为Data Race。根据官网上的定义(what is data race),Data Race出现是由以下原因导致:

  • 多个线程同时访问共享内存;
  • 至少有一个线程写该共享内存区域;
  • 线程访问共享内存并没有利用锁进行同步;
Java并发编程之线程

线程作为操作系统的最小调度单位。一个进程里可以有多个线程,这些线程有各自的程序计数器、堆栈空间和局部变量,而且可以共享进程的内存空间,因而在上下文切换时时间更短,效率更高,也常被成为轻量级进程(Light Weight Process)。接下来,将从三个方面来介绍Java线程类Thread的具体用法:

  • 线程构造与初始化;
  • 线程状态切换;
  • 线程变量ThreadLocal的使用

Thread: https://en.wikipedia.org/wiki/Thread_(computing)

Picasso从使用到原理详解

Picasso是SquareUp公司开源的专门为Android平台量身制作的图片加载库。通过Picasso,用户可以方便的将图片加载到特定的ImageView中,而不用关心图片是在一个文件夹里,还是在一个服务器上。那么,Picasso是如何何实现图片的快速加载了?

  • 利用两级缓存机制对图片进行缓存: 加载一个图片时,首先从内存中查看是否存在;如果不存在,则查看外部存储是否有该图片。这时,如果还没有找到,则通过网络端下载图片;
  • 利用OkHttp库进行图片下载,下载后保存到缓存,下次请求时无需从网络端下载;如果出现网络错误,会自动重试下载;
《Effective Java》摘记

第一遍看完感觉没有学到什么,又看了一遍,然后自己找了些实例对比着理解了书上的要点,算是对Java编程有了更多的认识。以下是 《Effective Java 2nd edition》的摘记。

Consider static factory methods instead of constructors

相比构造函数,静态工厂方法有哪些优点了?首先,静态工厂方法有自己的名字,这可以增强程序的可读性;其次,静态工厂方法每次调用时,不用创建新的对象实例;第三,静态工厂方法可以返回其返回类型的任何子类型对象。

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

public final class Boolean implements java.io.Serializable,
Comparable<Boolean>
{

public static final Boolean TRUE = new Boolean(true);

public static final Boolean FALSE = new Boolean(false);

....
//根据boolean值返回相应的Boolean对象
public static Boolean valueOf(boolean b) {
return (b ? TRUE : FALSE);
}

}

如何在Java中调用C_C++方法

有时,需要在Java中直接调用本地(native)方法,把一些耗时的操作使用效率更高C/C++实现。在Java中调用本地方法通常被称为Java Native Interface(JNI)。那么,什么时候需要用到JNI了?

  • 需要在底层实现耗时更小、更快的程序
  • 在Java中需要调用本地代码库
  • 需要使用平台相关但Java标准库文件不支持的特性

接下来,我们就来看一看,如何在Java中通过JNI来调用本地方法?

Java程序编译过程

Java编译过程

一般,C/C++程序的编译过程可以分为5个步骤(见下图):Preprocessing(预处理),Parsing(解析), Translation(翻译),Assembling(汇编),Linking(链接)。

Java程序具有平台无关性,其在Java Virtual Machine(JVM)上执行,因此编译过程与C/C++大不相同:Java程序首先由编译器翻译成包含了Bytecode(字节码)的.class文件,程序执行时,由类加载器(class loader)将该类的字节码加载到JVM中,JVM会解释执行相应的Bytecode。