标签:web程序 hide 线程 业务逻辑 必须 重入 实例 out interrupt
解决方法:使用synchronized代码块去优化代码执行的时间,也就是减少锁的粒度;
实例:
SyncDubbo1.java 和 SyncDubbo2.java
/** * synchronized的重入 * @@author Maozw * */ public class SyncDubbo1 { public synchronized void method1(){ System.out.println("method1.."); method2(); } public synchronized void method2(){ System.out.println("method2.."); method3(); } public synchronized void method3(){ System.out.println("method3.."); } public static void main(String[] args) { final SyncDubbo1 sd = new SyncDubbo1(); Thread t1 = new Thread(new Runnable() { @Override public void run() { sd.method1(); } }); t1.start(); } }
/** * synchronized的重入 * @@author Maozw * */ public class SyncDubbo2 { static class Main { public int i = 10; public synchronized void operationSup(){ try { i--; System.out.println("Main print i = " + i); Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } } static class Sub extends Main { public synchronized void operationSub(){ try { while(i > 0) { i--; System.out.println("Sub print i = " + i); Thread.sleep(100); this.operationSup(); } } catch (InterruptedException e) { e.printStackTrace(); } } } public static void main(String[] args) { Thread t1 = new Thread(new Runnable() { @Override public void run() { Sub sub = new Sub(); sub.operationSub(); } }); t1.start(); } }
示例:SyncException.java
说明:对于web程序,异常释放锁的情况,如果来不及及时处理,很可能对应用程序的业务逻辑产出错误:如执行一个队列任务,很多对象都去等待第一个对象执行完成并释放锁,但是第一个对象由于异常原因,导致业务逻辑没有正常执行完成,就释放了锁,那么后续任务就会产生一些问题;所以这个问题需要注意;
/** * synchronized异常 * @@author Maozw * */ public class SyncException { private int i = 0; public synchronized void operation(){ while(true){ try { i++; Thread.sleep(100); System.out.println(Thread.currentThread().getName() + " , i = " + i); if(i == 20){ //Integer.parseInt("a"); throw new RuntimeException(); } } catch (InterruptedException e) { e.printStackTrace(); } } } public static void main(String[] args) { final SyncException se = new SyncException(); Thread t1 = new Thread(new Runnable() { @Override public void run() { se.operation(); } },"t1"); t1.start(); } }
使用synchronized声明的方法在某些情况下是比较极端的(存在弊端):线程A调用同步的方法执行一段很长时间的任务,那么B线程就必须等待比较长的时间才能执行;
* 解决方法:使用synchronized代码块去优化代码执行的时间,也就是减少锁的粒度;
* 示例:ObjectLock.java
* 说明:synchronized可以使用任务的Object对象进行加锁,用法比较灵活;
1 /** 2 * 使用synchronized代码块加锁,比较灵活 3 * @@author Maozw 4 * 5 */ 6 public class ObjectLock { 7 8 public void method1(){ 9 synchronized (this) { //对象锁 10 try { 11 System.out.println("do method1.."); 12 Thread.sleep(2000); 13 } catch (InterruptedException e) { 14 e.printStackTrace(); 15 } 16 } 17 } 18 19 public void method2(){ //类锁 20 synchronized (ObjectLock.class) { 21 try { 22 System.out.println("do method2.."); 23 Thread.sleep(2000); 24 } catch (InterruptedException e) { 25 e.printStackTrace(); 26 } 27 } 28 } 29 30 private Object lock = new Object(); 31 public void method3(){ //任何对象锁 32 synchronized (lock) { 33 try { 34 System.out.println("do method3.."); 35 Thread.sleep(2000); 36 } catch (InterruptedException e) { 37 e.printStackTrace(); 38 } 39 } 40 } 41 42 43 public static void main(String[] args) { 44 45 final ObjectLock objLock = new ObjectLock(); 46 Thread t1 = new Thread(new Runnable() { 47 @Override 48 public void run() { 49 objLock.method1(); 50 } 51 }); 52 Thread t2 = new Thread(new Runnable() { 53 @Override 54 public void run() { 55 objLock.method2(); 56 } 57 }); 58 Thread t3 = new Thread(new Runnable() { 59 @Override 60 public void run() { 61 objLock.method3(); 62 } 63 }); 64 65 t1.start(); 66 t2.start(); 67 t3.start(); 68 } 69 }
* 示例:StringLock.java
* 说明:
/** * synchronized代码块对字符串的锁,注意String常量池的缓存功能 * @@author Maozw * */ public class StringLock { public void method() { //new String("字符串常量") synchronized ("字符串常量") { try { while(true){ System.out.println("当前线程 : " + Thread.currentThread().getName() + "开始"); Thread.sleep(1000); System.out.println("当前线程 : " + Thread.currentThread().getName() + "结束"); } } catch (InterruptedException e) { e.printStackTrace(); } } } public static void main(String[] args) { final StringLock stringLock = new StringLock(); Thread t1 = new Thread(new Runnable() { @Override public void run() { stringLock.method(); } },"t1"); Thread t2 = new Thread(new Runnable() { @Override public void run() { stringLock.method(); } },"t2"); t1.start(); t2.start(); } }
* 说明:
* 示例:ModifyLock.java
/** * 同一对象属性的修改不会影响锁的情况 * @@author Maozw * */ public class ModifyLock { private String name ; private int age ; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public synchronized void changeAttributte(String name, int age) { try { System.out.println("当前线程 : " + Thread.currentThread().getName() + " 开始"); this.setName(name); this.setAge(age); System.out.println("当前线程 : " + Thread.currentThread().getName() + " 修改对象内容为: " + this.getName() + ", " + this.getAge()); Thread.sleep(2000); System.out.println("当前线程 : " + Thread.currentThread().getName() + " 结束"); } catch (InterruptedException e) { e.printStackTrace(); } } public static void main(String[] args) { final ModifyLock modifyLock = new ModifyLock(); Thread t1 = new Thread(new Runnable() { @Override public void run() { modifyLock.changeAttributte("张三", 20); } },"t1"); Thread t2 = new Thread(new Runnable() { @Override public void run() { modifyLock.changeAttributte("李四", 21); } },"t2"); t1.start(); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } t2.start(); } }
* 说明: 在设计程序时就应该避免双方相互持有对方的锁的情况
* 示例:
/** * 死锁问题,在设计程序时就应该避免双方相互持有对方的锁的情况 * @@author Maozw * */ public class DeadLock implements Runnable{ private String tag; private static Object lock1 = new Object(); private static Object lock2 = new Object(); public void setTag(String tag){ this.tag = tag; } @Override public void run() { if(tag.equals("a")){ synchronized (lock1) { try { System.out.println("当前线程 : " + Thread.currentThread().getName() + " 进入lock1执行"); Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (lock2) { System.out.println("当前线程 : " + Thread.currentThread().getName() + " 进入lock2执行"); } } } if(tag.equals("b")){ synchronized (lock2) { try { System.out.println("当前线程 : " + Thread.currentThread().getName() + " 进入lock2执行"); Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (lock1) { System.out.println("当前线程 : " + Thread.currentThread().getName() + " 进入lock1执行"); } } } } public static void main(String[] args) { DeadLock d1 = new DeadLock(); d1.setTag("a"); DeadLock d2 = new DeadLock(); d2.setTag("b"); Thread t1 = new Thread(d1, "t1"); Thread t2 = new Thread(d2, "t2"); t1.start(); try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } t2.start(); } }
标签:web程序 hide 线程 业务逻辑 必须 重入 实例 out interrupt
原文地址:https://www.cnblogs.com/Mao-admin/p/9988489.html