import java.util.LinkedList; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; /** * BlockingQueue:顾名思义,首先它是一个队列,并且支持阻塞的机制,阻塞的放入和得到数据。 * 我们要实现LinkedBlockingQueue下面两个简单的方法put和take。 * put(anobject):把anObject加到BlockingQueue里,如果BlockQueue没有空间,则调用此方法的 * 线程被阻断,直到BlockingQueue里面有空间再继续。 * take:取走BlockingQueue里排在首位的对象,若BlockingQueue为空,阻断进入等待状态直到 * BlockingQueue有新的数据被加入。 */ public class MyQueue { //1. 需要一个承装元素的集合 private LinkedList<Object> list = new LinkedList<Object>(); //2.需要一个计数器 private AtomicInteger count = new AtomicInteger(0); //3.需要制定上限和下限 private final int minSize = 0; private final int maxSize; //4. 构造方法 public MyQueue(int size){ this.maxSize = size; } //5. 初始化一个对象用于加锁 private final Object lock = new Object(); //put(anObject): 把anObject放到BlockingQueue里,如果BlockQueue没有空间,则调用此方法的线程被阻断,直到BlockingQueue里面有空间再继续 public void put(Object obj){ synchronized (lock){ while(count.get() == this.maxSize){ try { lock.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } // 1 加入元素 list.add(obj); // 2 计数器增加 count.incrementAndGet(); // 3 通知另外一个线程(唤醒) lock.notify(); System.out.println("新加入的元素为:" + obj); } } //take: 取走BlockingQueue里排在首位的对象,若BolckingQueue为空,阻断进入等待状态 //直到BlockingQueue有新的数据被加入 public Object take(){ Object ret = null; synchronized (lock){ while(count.get() == this.minSize){ try { lock.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } //1 做移除元素操作 ret = list.removeFirst(); //2 计数器递减 count.decrementAndGet(); //3 唤醒另外一个线程 lock.notify(); } return ret; } public int getSize(){ return this.count.get(); } public static void main(String[] args) { final MyQueue mq = new MyQueue(5); mq.put("a"); mq.put("b"); mq.put("c"); mq.put("d"); mq.put("e"); System.out.println("当前容器的长度:" + mq.getSize()); Thread t1 = new Thread(new Runnable() { public void run() { mq.put("f"); mq.put("g"); } },"t1"); t1.start(); Thread t2 = new Thread(new Runnable() { public void run() { Object o1 = mq.take(); System.out.println("移除的元素为:" + o1); Object o2 = mq.take(); System.out.println("移除的元素为:" + o2); } },"t2"); try { TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { e.printStackTrace(); } t2.start(); } /** * 新加入的元素为:a * 新加入的元素为:b * 新加入的元素为:c * 新加入的元素为:d * 新加入的元素为:e * 当前容器的长度:5 * 新加入的元素为:f * 移除的元素为:a * 移除的元素为:b * 新加入的元素为:g * * 解析: 可能打印顺序不对 */
}
public class ChangeLock { private String lock = "lock"; private void method(){ synchronized (lock){ try { System.out.println("当前线程:" + Thread.currentThread().getName() + "开始"); lock = "change lock"; Thread.sleep(2000); System.out.println("当前线程:" + Thread.currentThread().getName() + "结束"); } catch (InterruptedException e) { e.printStackTrace(); } } } public static void main(String[] args) { final ChangeLock changeLock = new ChangeLock(); Thread t1 = new Thread(new Runnable() { public void run() { changeLock.method(); } },"t1"); Thread t2 = new Thread(new Runnable() { public void run() { changeLock.method(); } },"t2"); t1.start(); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } t2.start(); } /** * 执行结果: * 当前线程:t1开始 * 当前线程:t2开始 * 当前线程:t1结束 * 当前线程:t2结束 */ }
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; } 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(); } /** * 两线程相互虚弱对方造成死锁 */ }
/** * 同一对象属性的修改不会影响锁的情况 */ 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 changeAttribute(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() { public void run() { modifyLock.changeAttribute("张三",20); } },"t1"); Thread t2 = new Thread(new Runnable() { public void run() { modifyLock.changeAttribute("李四",21); } },"t2"); t1.start(); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } t2.start(); } /** * 当前线程:t1开始 * 当前线程:t1修改对象内容为:张三,20 * 当前线程:t1结束 * 当前线程:t2开始 * 当前线程:t2修改对象内容为:李四,21 * 当前线程:t2结束 */ }
/** * 使用synchronized代码块加锁,比较灵活 */ public class ObjectLock { public void method1(){ synchronized (this){ //对象锁 try { System.out.println("do method1.."); Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } } } public void method2(){ synchronized (ObjectLock.class){ //类锁 try { System.out.println("do method2.."); Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } } } private Object lock = new Object(); public void method3(){ //任何对象锁 synchronized (lock){ try { System.out.println("do method3.."); Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } } } public static void main(String[] args) { final ObjectLock objLock = new ObjectLock(); Thread t1 = new Thread(new Runnable(){ public void run() { objLock.method1(); } }); Thread t2 = new Thread(new Runnable() { public void run() { objLock.method2(); } }); Thread t3 = new Thread(new Runnable() { public void run() { objLock.method3(); } }); t1.start(); t2.start(); t3.start(); } }
/** * 使用synchronized代码块减小锁的粒度,提高性能 */ public class Optimize { public void doLongTimeTask(){ try { System.out.println("当前线程开始:" + Thread.currentThread().getName() + ",正在执行一个较长时间的业务操作,其内容不需要同步"); Thread.sleep(2000); synchronized (this){ 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 Optimize otz = new Optimize(); Thread t1 = new Thread(new Runnable() { public void run() { otz.doLongTimeTask(); } },"t1"); Thread t2 = new Thread(new Runnable() { public void run() { otz.doLongTimeTask(); } },"t2"); t1.start(); t2.start(); } /** * 执行结果: * 当前线程开始:t1,正在执行一个较长时间的业务操作,其内容不需要同步 * 当前线程开始:t2,正在执行一个较长时间的业务操作,其内容不需要同步 * 当前线程:t1,执行同步代码块,对其同步变量进行操作 * 当前线程结束:t1,执行完毕 * 当前线程:t2,执行同步代码块,对其同步变量进行操作 * 当前线程结束:t2,执行完毕 */ }
/** * synchronized 代码块对字符串的锁,注意String常量池的缓存功能 */ public class StringLock { public void method(){ synchronized (new String("字符串常量")){ 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() { public void run() { stringLock.method(); } },"t1"); Thread t2 = new Thread(new Runnable() { public void run() { stringLock.method(); } },"t2"); t1.start(); t2.start(); } /** * new String new出两个对象 */ }
/** * ThreadLocal概念:线程局部变量,是一种多线程间并发访问变量的解决方案。 * 与其synchronized等加锁的方式不同,ThreadLocal完全不提供锁,而使用以 * 空间换时间的手段,为每个线程提供变量的独立副本,以保证线程安全。 * * 从性能上说,ThreadLocal不具有绝对的优势,在并发不是很高的时候,加锁的性能会更好, * 但作为一套与锁完全无关的线程安全解决方案,在高并发量或者竞争激烈的场景,使用 * ThreadLocal可以在一定程度上减少锁竞争。 */
public class ConnThreadLocal { /** * 当前这个线程设置这个变量跟另外一个线程他们俩是不可见的 */ public static ThreadLocal<String> th = new ThreadLocal<String>(); public void setTh(String value){ th.set(value); } public void getTh(){ System.out.println(Thread.currentThread().getName() + ":" + this.th.get()); } public static void main(String[] args) { final ConnThreadLocal ct = new ConnThreadLocal(); Thread t1 = new Thread(new Runnable() { public void run() { ct.setTh("张三"); ct.getTh(); } },"t1"); Thread t2 = new Thread(new Runnable() { public void run() { try { Thread.sleep(1000); ct.getTh(); } catch (InterruptedException e) { e.printStackTrace(); } } },"t2"); t1.start(); t2.start(); } /** * 征对这个线程内是有效的 * t1:张三 * t2:null */ }
/** * 单例模式,最常见的就是饥饿模式,和懒汉模式,一个直接实例化对象,一个在调用方法时 * 进行实例化对象。在多线程模式中,考虑到性能和线程安全问题,我们一般选择下面两种比较 * 经典的单例模式,在性能提高的同时,又保证了线程安全。 * dubble check instance * static inner class */ public class DubbleSingleton { private static DubbleSingleton ds; public static DubbleSingleton getDs(){ if(ds == null){ try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (DubbleSingleton.class){ if(ds == null){ ds = new DubbleSingleton(); } } } return ds; } public static void main(String[] args) { Thread t1 = new Thread(new Runnable() { public void run() { System.out.println(DubbleSingleton.getDs().hashCode()); } },"t1"); Thread t2 = new Thread(new Runnable() { public void run() { System.out.println(DubbleSingleton.getDs().hashCode()); } },"t2"); Thread t3 = new Thread(new Runnable() { public void run() { System.out.println(DubbleSingleton.getDs().hashCode()); } },"t3"); t1.start(); t2.start(); t3.start(); } }
public class Singletion { private static class InnerSingletion{ private static Singletion singletion = new Singletion(); } public static Singletion getInstance(){ return InnerSingletion.singletion; } }