Effective Java-学习笔记(10-11章)
2017-05-13 20:15
381 查看
并发
66.同步访问共享的可变数据
private static boolean isStop = true; Thread myThread = new Thread(new Runnable() { @Override public void run() { int i = 0; while (isStop) { i++; Log.i("clp", "i=" + i); } } }); myThread.start(); try { Thread.sleep(1000); } catch (Exception e) { } isStop = false;
上面的代码Thread的线程看不到isStop值的修改,所以会一直执行下去。
一种方式是添加volatile。private static volatile boolean isStop = true;
private static synchronized void requestStop() { isStop = true; } private static synchronized boolean stopRequested() { return isStop; } private static boolean isStop = false; Thread myThread = new Thread(new Runnable() { @Override public void run() { int i = 0; while (!stopRequested()) { i++; Log.i("clp", "i=" + i); } } }); myThread.start(); try { Thread.sleep(1000); } catch (Exception e) { } requestStop();
67.避免过度同步
1.在同步块中不要调用外来方法RE:你不知道外来方法执行了什么操作
2.尽量减少同步块中代码的工作量
RE:在多核的设备上,这样会耗费性能(持续等待)
锁,是指当前线程持有的话,其他线程要想调用,需要等待当前线程的锁释放,但是如果当前线程执行到同步的代码,可以直接执行。
public class CldSyncUtil { private static Object object = new Object(); public static String getName() { synchronized (object) {//因为getFullName中的方法直接调用getName,是在同一个线程,所以可以直接使用 Log.i("clp", "a"); return "a"; } } public static String getFullName() { synchronized (object) { Log.i("clp", "b"); return "b" + getName();//调用同样需要同步锁的getName方法 } } }
for (int j = 0; j < 10; j++) { Log.i("clp", CldSyncUtil.getFullName()); }
05-08 17:10:10.291 3473-3473/old.pkg.com.myapplicati I/clp: b 05-08 17:10:10.292 3473-3473/old.pkg.com.myapplicati I/clp: a 05-08 17:10:10.292 3473-3473/old.pkg.com.myapplicati I/clp: ba 05-08 17:10:10.292 3473-3473/old.pkg.com.myapplicati I/clp: b 05-08 17:10:10.292 3473-3473/old.pkg.com.myapplicati I/clp: a 05-08 17:10:10.292 3473-3473/old.pkg.com.myapplicati I/clp: ba
上面的这种写法,代码会顺序执行。因为第一次调用,会锁住对象,for循环后面的要等待。
public class CldSyncUtil { private static Object object = new Object(); public static String getName() { Log.i("clp", "getName thread=" + Thread.currentThread().getId()); synchronized (object) {//因为getFullName中的方法直接调用getName,是在同一个线程,所以可以直接使用 Log.i("clp", "a"); return "a"; } } public static String getFullName() { Log.i("clp", "getFullName thread =" + Thread.currentThread().getId()); synchronized (object) { Log.i("clp", "b"); return "b" + getName();//调用同样需要同步锁的getName方法 } } }
for (int j = 0; j < 5; j++) { new Thread(new Runnable() { @Override public void run() { Log.i("clp", CldSyncUtil.getFullName()); } }).start(); }
05-08 17:26:20.159 4239-4256/old.pkg.com.myapplicati I/clp: getFullName thread =178 05-08 17:26:20.159 4239-4256/old.pkg.com.myapplicati I/clp: b thread =178 05-08 17:26:20.159 4239-4256/old.pkg.com.myapplicati I/clp: getName thread=178 05-08 17:26:20.159 4239-4256/old.pkg.com.myapplicati I/clp: a thread =178 05-08 17:26:20.161 4239-4255/old.pkg.com.myapplicati I/clp: getFullName thread =177 05-08 17:26:20.161 4239-4255/old.pkg.com.myapplicati I/clp: b thread =177 05-08 17:26:20.161 4239-4255/old.pkg.com.myapplicati I/clp: getName thread=177 05-08 17:26:20.161 4239-4255/old.pkg.com.myapplicati I/clp: a thread =177 05-08 17:26:20.168 4239-4259/old.pkg.com.myapplicati I/clp: getFullName thread =181 05-08 17:26:20.169 4239-4259/old.pkg.com.myapplicati I/clp: b thread =181 05-08 17:26:20.169 4239-4259/old.pkg.com.myapplicati I/clp: getName thread=181 05-08 17:26:20.169 4239-4259/old.pkg.com.myapplicati I/clp: a thread =181 05-08 17:26:20.169 4239-4257/old.pkg.com.myapplicati I/clp: getFullName thread =179 05-08 17:26:20.169 4239-4257/old.pkg.com.myapplicati I/clp: b thread =179 05-08 17:26:20.169 4239-4257/old.pkg.com.myapplicati I/clp: getName thread=179 05-08 17:26:20.169 4239-4257/old.pkg.com.myapplicati I/clp: a thread =179 05-08 17:26:20.172 4239-4258/old.pkg.com.myapplicati I/clp: getFullName thread =180 05-08 17:26:20.172 4239-4258/old.pkg.com.myapplicati I/clp: b thread =180 05-08 17:26:20.172 4239-4258/old.pkg.com.myapplicati I/clp: getName thread=180 05-08 17:26:20.172 4239-4258/old.pkg.com.myapplicati I/clp: a thread =180
上面的写法,那个占用了锁,就会执行完,然后再释放给其他线程使用。
private static Object object = new Object(); public static String getName() { Log.i("clp", "getName thread=" + Thread.currentThread().getId()); synchronized (object) {//因为getFullName中的方法直接调用getName,是在同一个线程,所以可以直接使用 Log.i("clp", "a thread =" + Thread.currentThread().getId()); return "a"; } } public static String getFullName() { Log.i("clp", "getFullName thread =" + Thread.currentThread().getId()); synchronized (object) { Log.i("clp", "b thread =" + Thread.currentThread().getId()); return "b" + getName();//调用同样需要同步锁的getName方法 } }
for (int j = 0; j < 5; j++) { final int index = j; new Thread(new Runnable() { @Override public void run() { CldSyncUtil.getFullName(); } }).start(); }
05-08 17:18:55.095 4039-4056/old.pkg.com.myapplicati I/clp: getName thread=175 05-08 17:18:55.095 4039-4058/old.pkg.com.myapplicati I/clp: getName thread=177 05-08 17:18:55.095 4039-4056/old.pkg.com.myapplicati I/clp: a thread =175 05-08 17:18:55.096 4039-4058/old.pkg.com.myapplicati I/clp: a thread =177 05-08 17:18:55.097 4039-4054/old.pkg.com.myapplicati I/clp: getName thread=173 05-08 17:18:55.097 4039-4054/old.pkg.com.myapplicati I/clp: a thread =173 05-08 17:18:55.098 4039-4057/old.pkg.com.myapplicati I/clp: getFullName thread =176 05-08 17:18:55.098 4039-4057/old.pkg.com.myapplicati I/clp: b thread =176 05-08 17:18:55.098 4039-4057/old.pkg.com.myapplicati I/clp: getName thread=176 05-08 17:18:55.098 4039-4057/old.pkg.com.myapplicati I/clp: a thread =176 05-08 17:18:55.098 4039-4055/old.pkg.com.myapplicati I/clp: getFullName thread =174 05-08 17:18:55.098 4039-4055/old.pkg.com.myapplicati I/clp: b thread =174 05-08 17:18:55.098 4039-4055/old.pkg.com.myapplicati I/clp: getName thread=174 05-08 17:18:55.098 4039-4055/old.pkg.com.myapplicati I/clp: a thread =174
上面的两种方式,都是线程外,会快速执行完毕。 但是线程内部,要等待其中一个线程(持有锁),执行完毕之后,释放锁,另外一个线程再获得锁,去执行。
68.executor和task优先于线程
使用线程池。工程用会大量使用到线程的地方,最好封装一个工具类,统一来调度。
相关文章推荐
- Effective Java 学习笔记 (10)
- Effective Java 学习笔记 (10)
- effective-java 学习笔记(1)
- effective Java 学习笔记 (一)
- Effective Java 学习笔记(2)
- Effective Java 学习笔记(2)
- effective-java学习笔记(2)避免在程序中创建重复的对象
- effective java 学习笔记(二)
- Effective Java 学习笔记(3)
- 孙鑫JAVA学习笔记9-10
- Effective Java 学习笔记(8)
- effective Java 学习笔记(三)
- Effective Java 学习笔记(4)
- Effective Java 学习笔记(二)
- Java学习笔记10
- Effective Java 学习笔记 (五)
- Effective Java 学习笔记 (六)
- Effective Java 学习笔记 (7)
- Effective Java 学习笔记(5)
- Effective Java 学习笔记(1)