Effective Java-学习笔记(10-11章)
来源:互联网 发布:阿里云企业邮箱设置 编辑:程序博客网 时间:2024/06/05 00:08
并发
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: b05-08 17:10:10.292 3473-3473/old.pkg.com.myapplicati I/clp: a05-08 17:10:10.292 3473-3473/old.pkg.com.myapplicati I/clp: ba05-08 17:10:10.292 3473-3473/old.pkg.com.myapplicati I/clp: b05-08 17:10:10.292 3473-3473/old.pkg.com.myapplicati I/clp: a05-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 =17805-08 17:26:20.159 4239-4256/old.pkg.com.myapplicati I/clp: b thread =17805-08 17:26:20.159 4239-4256/old.pkg.com.myapplicati I/clp: getName thread=17805-08 17:26:20.159 4239-4256/old.pkg.com.myapplicati I/clp: a thread =17805-08 17:26:20.161 4239-4255/old.pkg.com.myapplicati I/clp: getFullName thread =17705-08 17:26:20.161 4239-4255/old.pkg.com.myapplicati I/clp: b thread =17705-08 17:26:20.161 4239-4255/old.pkg.com.myapplicati I/clp: getName thread=17705-08 17:26:20.161 4239-4255/old.pkg.com.myapplicati I/clp: a thread =17705-08 17:26:20.168 4239-4259/old.pkg.com.myapplicati I/clp: getFullName thread =18105-08 17:26:20.169 4239-4259/old.pkg.com.myapplicati I/clp: b thread =18105-08 17:26:20.169 4239-4259/old.pkg.com.myapplicati I/clp: getName thread=18105-08 17:26:20.169 4239-4259/old.pkg.com.myapplicati I/clp: a thread =18105-08 17:26:20.169 4239-4257/old.pkg.com.myapplicati I/clp: getFullName thread =17905-08 17:26:20.169 4239-4257/old.pkg.com.myapplicati I/clp: b thread =17905-08 17:26:20.169 4239-4257/old.pkg.com.myapplicati I/clp: getName thread=17905-08 17:26:20.169 4239-4257/old.pkg.com.myapplicati I/clp: a thread =17905-08 17:26:20.172 4239-4258/old.pkg.com.myapplicati I/clp: getFullName thread =18005-08 17:26:20.172 4239-4258/old.pkg.com.myapplicati I/clp: b thread =18005-08 17:26:20.172 4239-4258/old.pkg.com.myapplicati I/clp: getName thread=18005-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=17505-08 17:18:55.095 4039-4058/old.pkg.com.myapplicati I/clp: getName thread=17705-08 17:18:55.095 4039-4056/old.pkg.com.myapplicati I/clp: a thread =17505-08 17:18:55.096 4039-4058/old.pkg.com.myapplicati I/clp: a thread =17705-08 17:18:55.097 4039-4054/old.pkg.com.myapplicati I/clp: getName thread=17305-08 17:18:55.097 4039-4054/old.pkg.com.myapplicati I/clp: a thread =17305-08 17:18:55.098 4039-4057/old.pkg.com.myapplicati I/clp: getFullName thread =17605-08 17:18:55.098 4039-4057/old.pkg.com.myapplicati I/clp: b thread =17605-08 17:18:55.098 4039-4057/old.pkg.com.myapplicati I/clp: getName thread=17605-08 17:18:55.098 4039-4057/old.pkg.com.myapplicati I/clp: a thread =17605-08 17:18:55.098 4039-4055/old.pkg.com.myapplicati I/clp: getFullName thread =17405-08 17:18:55.098 4039-4055/old.pkg.com.myapplicati I/clp: b thread =17405-08 17:18:55.098 4039-4055/old.pkg.com.myapplicati I/clp: getName thread=17405-08 17:18:55.098 4039-4055/old.pkg.com.myapplicati I/clp: a thread =174
上面的两种方式,都是线程外,会快速执行完毕。 但是线程内部,要等待其中一个线程(持有锁),执行完毕之后,释放锁,另外一个线程再获得锁,去执行。
68.executor和task优先于线程
使用线程池。
工程用会大量使用到线程的地方,最好封装一个工具类,统一来调度。
0 0
- Effective Java-学习笔记(10-11章)
- Effective Java 学习笔记 (11)
- Effective Java 学习笔记 (11)
- effective java学习笔记
- Effective java学习笔记
- effective java学习笔记
- effective java 学习笔记
- Effective Java 学习笔记
- Effective Java 学习笔记
- Effective Java学习笔记
- Effective Java学习笔记
- Effective Java学习笔记
- Effective Java 学习笔记
- Effective java --学习笔记
- Effective Java 学习笔记 (10)
- Effective Java 学习笔记 (10)
- Effective Java-学习笔记(6-9章)
- 《Effective Java 学习笔记 第二章》
- 1033. 旧键盘打字(20)
- (转)外边合并问题
- 1034. 有理数四则运算(20)
- python笔记
- 1036. 跟奥巴马一起编程(15)
- Effective Java-学习笔记(10-11章)
- ThinkPHP5.0-请求
- apk签名信息查看
- 1037. 在霍格沃茨找零钱(20)
- 12号c总结
- windows7下安装centos7系统或者单独装centos7
- MySql的一些内置函数
- Java基础——方法的重载和重写的区别与分析
- 1038. 统计同成绩学生(20)